mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
[Security Solution] remove old and skipped Threat Intelligence Cypress tests (#191166)
This commit is contained in:
parent
c492036aed
commit
8377275c44
54 changed files with 21 additions and 6491 deletions
|
@ -21,8 +21,6 @@ disabled:
|
|||
- x-pack/test/osquery_cypress/visual_config.ts
|
||||
- x-pack/test/security_solution_cypress/cli_config.ts
|
||||
- x-pack/test/security_solution_cypress/config.ts
|
||||
- x-pack/test/threat_intelligence_cypress/cli_config_parallel.ts
|
||||
- x-pack/test/threat_intelligence_cypress/config.ts
|
||||
|
||||
# Playwright
|
||||
- x-pack/test/security_solution_playwright/playwright.config.ts
|
||||
|
|
|
@ -386,24 +386,6 @@ steps:
|
|||
- exit_status: '-1'
|
||||
limit: 1
|
||||
|
||||
- command: .buildkite/scripts/steps/functional/threat_intelligence.sh
|
||||
label: 'Threat Intelligence Cypress Tests'
|
||||
agents:
|
||||
image: family/kibana-ubuntu-2004
|
||||
imageProject: elastic-images-prod
|
||||
provider: gcp
|
||||
machineType: n2-standard-4
|
||||
preemptible: true
|
||||
depends_on:
|
||||
- build
|
||||
- quick_checks
|
||||
timeout_in_minutes: 60
|
||||
parallelism: 1
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: '-1'
|
||||
limit: 1
|
||||
|
||||
- command: .buildkite/scripts/steps/functional/osquery_cypress.sh
|
||||
label: 'Osquery Cypress Tests'
|
||||
agents:
|
||||
|
|
|
@ -321,23 +321,6 @@ steps:
|
|||
- exit_status: '-1'
|
||||
limit: 1
|
||||
|
||||
- command: .buildkite/scripts/steps/functional/threat_intelligence.sh
|
||||
label: 'Threat Intelligence Cypress Tests'
|
||||
agents:
|
||||
image: family/kibana-ubuntu-2004
|
||||
imageProject: elastic-images-prod
|
||||
provider: gcp
|
||||
machineType: n2-standard-4
|
||||
preemptible: true
|
||||
depends_on:
|
||||
- build
|
||||
timeout_in_minutes: 60
|
||||
parallelism: 1
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: '-1'
|
||||
limit: 1
|
||||
|
||||
- command: .buildkite/scripts/steps/functional/osquery_cypress.sh
|
||||
label: 'Osquery Cypress Tests'
|
||||
agents:
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
steps:
|
||||
- command: .buildkite/scripts/steps/functional/threat_intelligence.sh
|
||||
label: 'Threat Intelligence Cypress Tests'
|
||||
agents:
|
||||
machineType: n2-standard-4
|
||||
preemptible: true
|
||||
depends_on:
|
||||
- build
|
||||
- quick_checks
|
||||
timeout_in_minutes: 60
|
||||
parallelism: 1
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: '-1'
|
||||
limit: 1
|
|
@ -245,22 +245,35 @@ const getPipeline = (filename: string, removeSteps = true) => {
|
|||
if (
|
||||
(await doAnyChangesMatch([
|
||||
/^package.json/,
|
||||
/^packages\/kbn-doc-links/,
|
||||
/^packages\/kbn-es-query/,
|
||||
/^packages\/kbn-i18n-react/,
|
||||
/^packages\/kbn-i18n/,
|
||||
/^packages\/kbn-expandable-flyout/,
|
||||
/^packages\/kbn-securitysolution-.*/,
|
||||
/^packages\/kbn-securitysolution-io-ts-list-types/,
|
||||
/^packages\/shared-ux/,
|
||||
/^src\/core/,
|
||||
/^src\/plugins\/data/,
|
||||
/^src\/plugins\/kibana_utils/,
|
||||
/^src\/plugins\/inspector/,
|
||||
/^x-pack\/packages\/kbn-elastic-assistant/,
|
||||
/^x-pack\/packages\/kbn-elastic-assistant-common/,
|
||||
/^x-pack\/packages\/security-solution/,
|
||||
/^x-pack\/plugins\/alerting/,
|
||||
/^x-pack\/plugins\/cases/,
|
||||
/^x-pack\/plugins\/data_views\/common/,
|
||||
/^x-pack\/plugins\/elastic_assistant/,
|
||||
/^x-pack\/plugins\/lists/,
|
||||
/^x-pack\/plugins\/rule_registry\/common/,
|
||||
/^x-pack\/plugins\/security_solution/,
|
||||
/^x-pack\/plugins\/security_solution_ess/,
|
||||
/^x-pack\/plugins\/security_solution_serverless/,
|
||||
/^x-pack\/plugins\/task_manager/,
|
||||
/^x-pack\/plugins\/threat_intelligence/,
|
||||
/^x-pack\/plugins\/timelines/,
|
||||
/^x-pack\/plugins\/triggers_actions_ui\/public\/application\/sections\/alerts_table/,
|
||||
/^x-pack\/plugins\/usage_collection\/public/,
|
||||
/^x-pack\/plugins\/elastic_assistant/,
|
||||
/^x-pack\/packages\/security-solution/,
|
||||
/^x-pack\/packages\/kbn-elastic-assistant/,
|
||||
/^x-pack\/packages\/kbn-elastic-assistant-common/,
|
||||
/^x-pack\/test\/functional\/es_archives\/security_solution/,
|
||||
/^x-pack\/test\/security_solution_cypress/,
|
||||
])) ||
|
||||
|
@ -271,37 +284,6 @@ const getPipeline = (filename: string, removeSteps = true) => {
|
|||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(await doAnyChangesMatch([
|
||||
/^package.json/,
|
||||
/^src\/plugins\/data/,
|
||||
/^src\/plugins\/kibana_utils/,
|
||||
/^src\/plugins\/inspector/,
|
||||
/^src\/plugins\/data_views/,
|
||||
/^src\/core/,
|
||||
/^packages\/kbn-securitysolution-.*/,
|
||||
/^packages\/kbn-es-query/,
|
||||
/^packages\/kbn-securitysolution-io-ts-list-types/,
|
||||
/^packages\/kbn-i18n-react/,
|
||||
/^packages\/kbn-i18n/,
|
||||
/^packages\/shared-ux/,
|
||||
/^packages\/kbn-doc-links/,
|
||||
/^packages\/kbn-securitysolution-io-ts-list-types/,
|
||||
/^x-pack\/plugins\/threat_intelligence/,
|
||||
/^x-pack\/packages\/security-solution/,
|
||||
/^x-pack\/test\/threat_intelligence_cypress/,
|
||||
/^x-pack\/plugins\/cases/,
|
||||
/^x-pack\/plugins\/timelines/,
|
||||
/^x-pack\/plugins\/triggers_actions_ui/,
|
||||
/^x-pack\/plugins\/rule_registry/,
|
||||
])) ||
|
||||
GITHUB_PR_LABELS.includes('ci:all-cypress-suites')
|
||||
) {
|
||||
pipeline.push(
|
||||
getPipeline('.buildkite/pipelines/pull_request/security_solution/threat_intelligence.yml')
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
((await doAnyChangesMatch([
|
||||
/^x-pack\/plugins\/osquery/,
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source .buildkite/scripts/steps/functional/common.sh
|
||||
|
||||
export JOB=kibana-threat-intelligence-chrome
|
||||
export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION}
|
||||
|
||||
echo "--- Threat Intelligence Cypress tests (Chrome)"
|
||||
|
||||
BK_ANALYTICS_API_KEY=$(vault_get security-solution-ci threat-intelligence-bk-api-key)
|
||||
|
||||
BK_ANALYTICS_API_KEY=$BK_ANALYTICS_API_KEY yarn --cwd x-pack/plugins/threat_intelligence cypress:run
|
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -1506,7 +1506,6 @@ x-pack/test/security_solution_api_integration/test_suites/sources @elastic/secur
|
|||
|
||||
/x-pack/test/security_solution_cypress/cypress/e2e/investigations @elastic/security-threat-hunting-investigations
|
||||
/x-pack/test/security_solution_cypress/cypress/e2e/sourcerer/sourcerer_timeline.cy.ts @elastic/security-threat-hunting-investigations
|
||||
/x-pack/test/threat_intelligence_cypress @elastic/security-threat-hunting-investigations
|
||||
|
||||
x-pack/test/security_solution_cypress/cypress/screens/expandable_flyout @elastic/security-threat-hunting-investigations
|
||||
x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/security-threat-hunting-investigations
|
||||
|
|
|
@ -19,7 +19,5 @@ export const TS_PROJECTS = TsProject.loadAll({
|
|||
// are present or up-to-date, and users likely won't know how to manage either, so the
|
||||
// type check is explicitly disabled in this project for now
|
||||
'.buildkite/tsconfig.json',
|
||||
|
||||
'x-pack/plugins/threat_intelligence/cypress/tsconfig.json',
|
||||
],
|
||||
});
|
||||
|
|
|
@ -131,9 +131,5 @@ If changes are made to how developers build, test, interact with, or release cod
|
|||
|
||||
**E2E tests:**
|
||||
|
||||
```
|
||||
node scripts/build_kibana_platform_plugins
|
||||
cd x-pack/plugins/threat_intelligence
|
||||
yarn cypress:open-as-ci
|
||||
```
|
||||
Cypress tests are integrated with the Security Solution ones. Please refer to https://github.com/elastic/kibana/blob/main/x-pack/test/security_solution_cypress/cypress/README.md for more information
|
||||
|
||||
|
|
|
@ -66,26 +66,9 @@ see the file in order to adjust the amount of indicators generated. The default
|
|||
|
||||
## E2E
|
||||
|
||||
### Data fixtures and loading process
|
||||
|
||||
Use es_archives to export data for e2e testing purposes, like so:
|
||||
|
||||
```
|
||||
TEST_ES_PORT=9200 node scripts/es_archiver save x-pack/test/threat_intelligence_cypress/es_archives/threat_intelligence "logs-ti*"
|
||||
```
|
||||
|
||||
These can be loaded at will with `x-pack/plugins/threat_intelligence/cypress/tasks/es_archiver.ts` task.
|
||||
|
||||
You can use this approach to load separate data dumps for every test case, to cover all critical scenarios.
|
||||
|
||||
### Running locally
|
||||
|
||||
`cd` into plugin root and execute `yarn cypress:open-as-ci`
|
||||
|
||||
### CI Execution
|
||||
|
||||
The entry point for PR testing is `.buildkite/pipelines/pull_request/base.yml` file, see that for details on
|
||||
how the test suite is executed & extra options regarding parallelism, retrying etc.
|
||||
Cypress tests are integrated with the Security Solution ones. Please refer to https://github.com/elastic/kibana/blob/main/x-pack/test/security_solution_cypress/cypress/README.md for more information
|
||||
|
||||
## FAQ
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"plugins": ["cypress"],
|
||||
"extends": [
|
||||
"plugin:cypress/recommended"
|
||||
],
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"cypress/no-force": "warn",
|
||||
"import/no-extraneous-dependencies": "off"
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* 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 { defineCypressConfig } from '@kbn/cypress-config';
|
||||
|
||||
const CI = process.env.BUILDKITE === 'true';
|
||||
|
||||
/**
|
||||
* Converts seconds to milliseconds
|
||||
* @param s Seconds
|
||||
* @returns milliseconds
|
||||
*/
|
||||
const sToMs = (s: number) => s * 1000;
|
||||
|
||||
const LOCAL_CONFIG: Cypress.ConfigOptions<any> = {
|
||||
defaultCommandTimeout: sToMs(10),
|
||||
};
|
||||
|
||||
const CI_CONFIG: Cypress.ConfigOptions<any> = {
|
||||
defaultCommandTimeout: sToMs(120),
|
||||
};
|
||||
|
||||
export default defineCypressConfig({
|
||||
...(CI ? CI_CONFIG : LOCAL_CONFIG),
|
||||
execTimeout: 120000,
|
||||
pageLoadTimeout: 120000,
|
||||
retries: {
|
||||
runMode: 1,
|
||||
},
|
||||
screenshotsFolder: '../../../target/kibana-threat-intelligence/cypress/screenshots',
|
||||
trashAssetsBeforeRuns: false,
|
||||
video: false,
|
||||
videosFolder: '../../../target/kibana-threat-intelligence/cypress/videos',
|
||||
viewportHeight: 946,
|
||||
viewportWidth: 1680,
|
||||
env: {
|
||||
grepFilterSpecs: true,
|
||||
grepTags: '@ess',
|
||||
protocol: 'http',
|
||||
hostname: 'localhost',
|
||||
configport: '5601',
|
||||
},
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:5601',
|
||||
experimentalMemoryManagement: true,
|
||||
setupNodeEvents(on, config) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
return config;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
closeFlyout,
|
||||
navigateToThreatIntelligence,
|
||||
openFlyout,
|
||||
openFlyoutTakeAction,
|
||||
openIndicatorsTableMoreActions,
|
||||
} from '../tasks/common';
|
||||
import {
|
||||
fillBlocklistForm,
|
||||
openAddToBlockListFlyoutFromTable,
|
||||
openAddToBlocklistFromFlyout,
|
||||
} from '../tasks/blocklist';
|
||||
import { navigateToBlocklist } from '../tasks/common';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import {
|
||||
BLOCK_LIST_VALUE_INPUT,
|
||||
FLYOUT_ADD_TO_BLOCK_LIST_ITEM,
|
||||
INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON,
|
||||
SAVED_BLOCK_LIST_DESCRIPTION,
|
||||
SAVED_BLOCK_LIST_NAME,
|
||||
} from '../screens/blocklist';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
const FIRST_BLOCK_LIST_NEW_NAME = 'first blocklist entry';
|
||||
const FIRST_BLOCK_LIST_NEW_DESCRIPTION = 'the first description';
|
||||
const SECOND_BLOCK_LIST_NEW_NAME = 'second blocklist entry';
|
||||
const SECOND_BLOCK_LIST_NEW_DESCRIPTION = 'the second description';
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171783
|
||||
describe.skip('Block list with invalid indicators', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/invalid_indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/invalid_indicators_data');
|
||||
});
|
||||
|
||||
it('should disabled blocklist in the indicators table context menu item and flyout context menu items', () => {
|
||||
openIndicatorsTableMoreActions(3);
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON).should('be.disabled');
|
||||
|
||||
openFlyout(3);
|
||||
openFlyoutTakeAction();
|
||||
cy.get(FLYOUT_ADD_TO_BLOCK_LIST_ITEM).should('be.disabled');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Block list interactions', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it.skip('should add to block list from the indicators table and from flyout', () => {
|
||||
// first indicator is a valid indicator for add to blocklist feature
|
||||
const firstIndicatorId = 'd86e656455f985357df3063dff6637f7f3b95bb27d1769a6b88c7adecaf7763f';
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToBlockListFlyoutFromTable();
|
||||
|
||||
cy.get(BLOCK_LIST_VALUE_INPUT(firstIndicatorId));
|
||||
|
||||
fillBlocklistForm(FIRST_BLOCK_LIST_NEW_NAME, FIRST_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
navigateToBlocklist();
|
||||
|
||||
cy.get(SAVED_BLOCK_LIST_NAME).eq(0).should('have.text', FIRST_BLOCK_LIST_NEW_NAME);
|
||||
cy.get(SAVED_BLOCK_LIST_DESCRIPTION)
|
||||
.eq(0)
|
||||
.should('have.text', FIRST_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
// second indicator is a valid indicator for add to blocklist feature
|
||||
const secondIndicatorId = 'd3e2cf87eabf84ef929aaf8dad1431b3387f5a26de8ffb7a0c3c2a13f973c0ab';
|
||||
openFlyout(1);
|
||||
openFlyoutTakeAction();
|
||||
openAddToBlocklistFromFlyout();
|
||||
|
||||
cy.get(BLOCK_LIST_VALUE_INPUT(secondIndicatorId));
|
||||
|
||||
fillBlocklistForm(SECOND_BLOCK_LIST_NEW_NAME, SECOND_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
closeFlyout();
|
||||
navigateToBlocklist();
|
||||
|
||||
cy.get(SAVED_BLOCK_LIST_NAME).eq(0).should('have.text', SECOND_BLOCK_LIST_NEW_NAME);
|
||||
cy.get(SAVED_BLOCK_LIST_DESCRIPTION)
|
||||
.eq(0)
|
||||
.should('have.text', SECOND_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
});
|
||||
});
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
navigateToThreatIntelligence,
|
||||
openFlyout,
|
||||
openFlyoutTakeAction,
|
||||
openIndicatorsTableMoreActions,
|
||||
} from '../tasks/common';
|
||||
import {
|
||||
createNewCaseFromTI,
|
||||
navigateToCaseViaToaster,
|
||||
openAddToExistingCaseFlyoutFromTable,
|
||||
openAddToExistingCaseFromFlyout,
|
||||
openAddToNewCaseFlyoutFromTable,
|
||||
openAddToNewCaseFromFlyout,
|
||||
selectExistingCase,
|
||||
} from '../tasks/cases';
|
||||
import {
|
||||
CASE_COMMENT_EXTERNAL_REFERENCE,
|
||||
FLYOUT_ADD_TO_EXISTING_CASE_ITEM,
|
||||
FLYOUT_ADD_TO_NEW_CASE_ITEM,
|
||||
INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON,
|
||||
INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON,
|
||||
} from '../screens/cases';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
describe('Cases with invalid indicators', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/invalid_indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/invalid_indicators_data');
|
||||
});
|
||||
|
||||
it.skip('should disable the indicators table context menu items and flyout context menu items', () => {
|
||||
const documentsNumber = 22;
|
||||
openIndicatorsTableMoreActions(documentsNumber - 1);
|
||||
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON).should('be.disabled');
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON).should('be.disabled');
|
||||
|
||||
openFlyout(documentsNumber - 1);
|
||||
openFlyoutTakeAction();
|
||||
|
||||
cy.get(FLYOUT_ADD_TO_EXISTING_CASE_ITEM).should('be.disabled');
|
||||
cy.get(FLYOUT_ADD_TO_NEW_CASE_ITEM).should('be.disabled');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cases interactions', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it.skip('should add to new case and to existing case from the indicators table and the flyout', () => {
|
||||
cy.log('should add to new case when clicking on the button in the indicators table');
|
||||
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToNewCaseFlyoutFromTable();
|
||||
createNewCaseFromTI();
|
||||
navigateToCaseViaToaster();
|
||||
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
cy.log('should add to existing case when clicking on the button in the indicators table');
|
||||
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToExistingCaseFlyoutFromTable();
|
||||
selectExistingCase();
|
||||
navigateToCaseViaToaster();
|
||||
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
cy.log('should add to new case when clicking on the button in the indicators flyout');
|
||||
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
openAddToNewCaseFromFlyout();
|
||||
createNewCaseFromTI();
|
||||
|
||||
navigateToCaseViaToaster();
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
cy.log('should add to existing case when clicking on the button in the indicators flyout');
|
||||
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
openAddToExistingCaseFromFlyout();
|
||||
selectExistingCase();
|
||||
|
||||
navigateToCaseViaToaster();
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
});
|
||||
});
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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 { login, visit } from '../tasks/login';
|
||||
import {
|
||||
EMPTY_PAGE_BODY,
|
||||
EMPTY_PAGE_DOCS_LINK,
|
||||
EMPTY_PAGE_INTEGRATIONS_LINK,
|
||||
} from '../screens/empty_page';
|
||||
|
||||
const THREAT_INTEL_PATH = '/app/security/threat_intelligence/';
|
||||
|
||||
describe('Empty Page', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTEL_PATH);
|
||||
});
|
||||
|
||||
it('should render the empty page with link to docs and integrations, and navigate to integrations page', () => {
|
||||
cy.get(EMPTY_PAGE_BODY).should('be.visible');
|
||||
cy.get(EMPTY_PAGE_DOCS_LINK).should('be.visible');
|
||||
cy.get(EMPTY_PAGE_INTEGRATIONS_LINK).should('be.visible');
|
||||
|
||||
cy.get(EMPTY_PAGE_INTEGRATIONS_LINK).click();
|
||||
cy.url().should('include', '/app/integrations/browse/threat_intel');
|
||||
cy.get('h1').first().should('contain', 'Integrations');
|
||||
});
|
||||
});
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* 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 { clearQuery, enterQuery, navigateToIndicatorsTablePage } from '../tasks/indicators';
|
||||
import {
|
||||
ADD_INTEGRATIONS_BUTTON,
|
||||
BREADCRUMBS,
|
||||
DEFAULT_LAYOUT_TITLE,
|
||||
EMPTY_STATE,
|
||||
ENDING_BREADCRUMB,
|
||||
FIELD_BROWSER,
|
||||
FIELD_BROWSER_MODAL,
|
||||
FIELD_SELECTOR,
|
||||
FIELD_SELECTOR_INPUT,
|
||||
FIELD_SELECTOR_LIST,
|
||||
FIELD_SELECTOR_TOGGLE_BUTTON,
|
||||
FILTERS_GLOBAL_CONTAINER,
|
||||
FLYOUT_JSON,
|
||||
FLYOUT_TABLE,
|
||||
FLYOUT_TABS,
|
||||
FLYOUT_TITLE,
|
||||
INDICATOR_TYPE_CELL,
|
||||
INDICATORS_TABLE,
|
||||
INDICATORS_TABLE_FEED_NAME_COLUMN_HEADER,
|
||||
INDICATORS_TABLE_FIRST_SEEN_COLUMN_HEADER,
|
||||
INDICATORS_TABLE_INDICATOR_NAME_CELL,
|
||||
INDICATORS_TABLE_INDICATOR_NAME_COLUMN_HEADER,
|
||||
INDICATORS_TABLE_INDICATOR_TYPE_CELL,
|
||||
INDICATORS_TABLE_INDICATOR_TYPE_COLUMN_HEADER,
|
||||
INDICATORS_TABLE_LAST_SEEN_COLUMN_HEADER,
|
||||
INDICATORS_TABLE_ROW_CELL,
|
||||
INSPECTOR_BUTTON,
|
||||
INSPECTOR_PANEL,
|
||||
LEADING_BREADCRUMB,
|
||||
QUERY_INPUT,
|
||||
TABLE_CONTROLS,
|
||||
TIME_RANGE_PICKER,
|
||||
REFRESH_BUTTON,
|
||||
} from '../screens/indicators';
|
||||
import { login, visit, waitForPageToBeLoaded } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import {
|
||||
closeFlyout,
|
||||
navigateToFlyoutJsonTab,
|
||||
navigateToFlyoutTableTab,
|
||||
openFlyout,
|
||||
} from '../tasks/common';
|
||||
import { INDICATORS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_ICON } from '../screens/timeline';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
const URL_WITH_CONTRADICTORY_FILTERS =
|
||||
'/app/security/threat_intelligence/indicators?indicators=(filterQuery:(language:kuery,query:%27%27),filters:!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:%27%27,key:threat.indicator.type,negate:!f,params:(query:file),type:phrase),query:(match_phrase:(threat.indicator.type:file))),(%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:%27%27,key:threat.indicator.type,negate:!f,params:(query:url),type:phrase),query:(match_phrase:(threat.indicator.type:url)))),timeRange:(from:now/d,to:now/d))';
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171779
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171778
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171785
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171786
|
||||
describe.skip('Invalid Indicators', { tags: '@ess' }, () => {
|
||||
describe('verify the grid loads even with missing fields', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/invalid_indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
esArchiverUnload('threat_intelligence/invalid_indicators_data');
|
||||
});
|
||||
|
||||
it('should display data grid despite the missing fields', () => {
|
||||
cy.get(INDICATORS_TABLE).should('exist');
|
||||
|
||||
// there are 19 documents in the x-pack/test/threat_intelligence_cypress/es_archives/threat_intelligence/invalid_indicators_data/data.json
|
||||
const documentsNumber = 22;
|
||||
cy.get(INDICATORS_TABLE_ROW_CELL).should('have.length.gte', documentsNumber);
|
||||
|
||||
// the last 3 documents have no hash so the investigate in timeline button isn't rendered
|
||||
cy.get(INDICATORS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_ICON).should(
|
||||
'have.length',
|
||||
documentsNumber - 4
|
||||
);
|
||||
|
||||
// we should have 21 documents plus the header
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_CELL).should('have.length', documentsNumber + 1);
|
||||
|
||||
// this entry has no hash to we show - in the Indicator Name column
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_CELL)
|
||||
.eq(documentsNumber - 3)
|
||||
.should('contain.text', '-');
|
||||
|
||||
// this entry is missing the file key entirely
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_CELL)
|
||||
.eq(documentsNumber - 2)
|
||||
.should('contain.text', '-');
|
||||
|
||||
// this entry is missing the type field
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_CELL)
|
||||
.eq(documentsNumber - 1)
|
||||
.should('contain.text', '-');
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_TYPE_CELL)
|
||||
.eq(documentsNumber - 1)
|
||||
.should('contain.text', '-');
|
||||
|
||||
// this entry is missing the type field
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_CELL).last().should('contain.text', '-');
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_TYPE_CELL).last().should('contain.text', '-');
|
||||
});
|
||||
});
|
||||
|
||||
describe('verify the grid loads even with missing mappings and missing fields', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/missing_mappings_indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
esArchiverUnload('threat_intelligence/missing_mappings_indicators_data');
|
||||
});
|
||||
|
||||
it('should display data grid despite the missing mappings and missing fields', () => {
|
||||
cy.get(INDICATORS_TABLE).should('exist');
|
||||
|
||||
// there are 2 documents in the x-pack/test/threat_intelligence_cypress/es_archives/threat_intelligence/missing_mappings_indicators_data/data.json
|
||||
const documentsNumber = 2;
|
||||
cy.get(INDICATORS_TABLE_ROW_CELL).should('have.length.gte', documentsNumber);
|
||||
|
||||
// we should have 2 documents plus the header
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_CELL).should('have.length', documentsNumber + 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171781
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/171780
|
||||
describe.skip('Indicators', () => {
|
||||
before(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
describe('Indicators page loading', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('verify the fleet plugin integrations endpoint exists', () => {
|
||||
cy.request({
|
||||
method: 'GET',
|
||||
url: '/api/fleet/epm/packages',
|
||||
}).should((response) => expect(response.status).to.eq(200));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Indicators page basics', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('should render the basic page elements', () => {
|
||||
cy.get(BREADCRUMBS).should('exist');
|
||||
|
||||
cy.get(LEADING_BREADCRUMB).should('have.text', 'Security');
|
||||
|
||||
cy.get(ENDING_BREADCRUMB).should('have.text', 'Intelligence');
|
||||
|
||||
cy.get(DEFAULT_LAYOUT_TITLE).should('have.text', 'Indicators');
|
||||
|
||||
cy.get(INDICATORS_TABLE).should('exist');
|
||||
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_NAME_COLUMN_HEADER).should('exist');
|
||||
cy.get(INDICATORS_TABLE_INDICATOR_TYPE_COLUMN_HEADER).should('exist');
|
||||
cy.get(INDICATORS_TABLE_FEED_NAME_COLUMN_HEADER).should('exist');
|
||||
cy.get(INDICATORS_TABLE_FIRST_SEEN_COLUMN_HEADER).should('exist');
|
||||
cy.get(INDICATORS_TABLE_LAST_SEEN_COLUMN_HEADER).should('exist');
|
||||
|
||||
cy.get(FILTERS_GLOBAL_CONTAINER).should('exist');
|
||||
|
||||
cy.get(`${FILTERS_GLOBAL_CONTAINER} ${TIME_RANGE_PICKER}`).should('exist');
|
||||
|
||||
cy.get(`${FIELD_SELECTOR}`).should('exist');
|
||||
|
||||
cy.log('should show the indicator flyout on ioc click');
|
||||
|
||||
openFlyout(1);
|
||||
|
||||
cy.get(FLYOUT_TITLE).should('contain', 'Indicator details');
|
||||
|
||||
cy.get(FLYOUT_TABS).should('exist').children().should('have.length', 3);
|
||||
|
||||
cy.get(FLYOUT_TABS).should('exist');
|
||||
navigateToFlyoutTableTab();
|
||||
|
||||
cy.get(FLYOUT_TABLE).should('exist').and('contain.text', 'threat.indicator.type');
|
||||
|
||||
navigateToFlyoutJsonTab();
|
||||
cy.get(FLYOUT_JSON).should('exist').and('contain.text', 'threat.indicator.type');
|
||||
|
||||
closeFlyout();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Indicator page search', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it.skip('should handle all search actions', () => {
|
||||
cy.log('should narrow the results to url indicators when respective KQL search is executed');
|
||||
|
||||
enterQuery('threat.indicator.type: "url"{enter}');
|
||||
|
||||
// Check if query results are narrowed after search
|
||||
cy.get(INDICATOR_TYPE_CELL).should('not.contain.text', 'file');
|
||||
|
||||
clearQuery();
|
||||
enterQuery('threat.indicator.type: "file"{enter}');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).should('not.contain.text', 'url');
|
||||
|
||||
clearQuery();
|
||||
|
||||
cy.log('should go to the 2nd page');
|
||||
|
||||
navigateToIndicatorsTablePage(1);
|
||||
|
||||
cy.get(TABLE_CONTROLS).should('contain.text', 'Showing 26-50 of');
|
||||
|
||||
cy.log('should go to page 1 when search input is cleared');
|
||||
cy.get(QUERY_INPUT).should('exist').focus();
|
||||
cy.get(QUERY_INPUT).clear();
|
||||
cy.get(QUERY_INPUT).type('{enter}');
|
||||
|
||||
cy.get(TABLE_CONTROLS).should('contain.text', 'Showing 1-25 of');
|
||||
|
||||
cy.log('should reload the data when refresh button is pressed');
|
||||
cy.intercept(/bsearch/).as('search');
|
||||
|
||||
cy.get(REFRESH_BUTTON).should('exist').click();
|
||||
|
||||
cy.wait('@search');
|
||||
});
|
||||
});
|
||||
|
||||
describe('No items match search criteria', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
cy.visit(URL_WITH_CONTRADICTORY_FILTERS);
|
||||
waitForPageToBeLoaded();
|
||||
});
|
||||
|
||||
it('should handle no match search criterie', () => {
|
||||
cy.log('not display the table when contradictory filters are set');
|
||||
|
||||
cy.get(FLYOUT_TABLE).should('not.exist');
|
||||
|
||||
cy.get(EMPTY_STATE).should('exist').and('contain.text', 'No results');
|
||||
|
||||
cy.log('have the default selected field, then update when user selects');
|
||||
|
||||
const threatFeedName = 'threat.feed.name';
|
||||
cy.get(`${FIELD_SELECTOR_INPUT}`).eq(0).should('have.text', threatFeedName);
|
||||
|
||||
const timestamp: string = '@timestamp';
|
||||
|
||||
cy.get(`${FIELD_SELECTOR_TOGGLE_BUTTON}`).should('exist').click();
|
||||
|
||||
cy.get(`${FIELD_SELECTOR_LIST}`).should('exist').contains(timestamp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Field browser', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
describe('when field browser is triggered', () => {
|
||||
it('should render proper modal window', () => {
|
||||
cy.get('[data-test-subj="tiIndicatorsTable"]').within(() => {
|
||||
cy.get(FIELD_BROWSER).last().click();
|
||||
});
|
||||
|
||||
cy.get(FIELD_BROWSER_MODAL).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Request inspector', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('when inspector button is clicked it should render the inspector flyout', () => {
|
||||
cy.get(INSPECTOR_BUTTON).last().click();
|
||||
|
||||
cy.get(INSPECTOR_PANEL).contains('Indicators search requests');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Add integrations', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('when the global header add integrations button is clicked it should navigate to the Integrations page with Threat Intelligence category selected', () => {
|
||||
cy.get(ADD_INTEGRATIONS_BUTTON).click();
|
||||
|
||||
cy.url().should('include', 'threat_intel');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
closeFlyout,
|
||||
navigateToFlyoutTableTab,
|
||||
openFlyout,
|
||||
waitForViewToBeUpdated,
|
||||
} from '../tasks/common';
|
||||
import {
|
||||
clearKQLBar,
|
||||
filterInFromBarChartLegend,
|
||||
filterInFromFlyoutBlockItem,
|
||||
filterInFromFlyoutOverviewTable,
|
||||
filterInFromFlyoutTableTab,
|
||||
filterInFromTableCell,
|
||||
filterOutFromBarChartLegend,
|
||||
filterOutFromFlyoutBlockItem,
|
||||
filterOutFromFlyoutOverviewTable,
|
||||
filterOutFromFlyoutTableTab,
|
||||
filterOutFromTableCell,
|
||||
} from '../tasks/query_bar';
|
||||
import { INDICATOR_TYPE_CELL } from '../screens/indicators';
|
||||
import { KQL_FILTER } from '../screens/query_bar';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
describe('Indicators query bar interaction', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it.skip('should add filter to kql', () => {
|
||||
cy.log('filter in values when clicking in the barchart legend');
|
||||
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
filterInFromBarChartLegend();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in the barchart legend');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
filterOutFromBarChartLegend();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators table cell');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
filterInFromTableCell();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out and out values when clicking in an indicators table cell');
|
||||
|
||||
waitForViewToBeUpdated();
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
filterOutFromTableCell();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators flyout overview tab block');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterInFromFlyoutBlockItem();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in an indicators flyout overview block');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterOutFromFlyoutBlockItem();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators flyout overview tab table row');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterInFromFlyoutOverviewTable();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in an indicators flyout overview tab row');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterOutFromFlyoutOverviewTable();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators flyout table tab action column');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
navigateToFlyoutTableTab();
|
||||
filterInFromFlyoutTableTab();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in an indicators flyout table tab action column');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
navigateToFlyoutTableTab();
|
||||
filterOutFromFlyoutTableTab();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
});
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
addToTimelineFromBarchartLegend,
|
||||
addToTimelineFromFlyoutOverviewTabBlock,
|
||||
addToTimelineFromFlyoutOverviewTabTable,
|
||||
addToTimelineFromTableCell,
|
||||
closeTimeline,
|
||||
investigateInTimelineFromFlyout,
|
||||
investigateInTimelineFromTable,
|
||||
openTimeline,
|
||||
} from '../tasks/timeline';
|
||||
import { closeFlyout, openFlyout, openFlyoutTakeAction } from '../tasks/common';
|
||||
import {
|
||||
TIMELINE_AND_OR_BADGE,
|
||||
TIMELINE_DATA_PROVIDERS_WRAPPER,
|
||||
TIMELINE_DRAGGABLE_ITEM,
|
||||
} from '../screens/timeline';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import { login, visit } from '../tasks/login';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
describe('Timeline', { tags: '@ess' }, () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
// TODO: This appears to already be failing on main.
|
||||
it.skip('should verify add to timeline and investigate in timeline work from various places', () => {
|
||||
cy.log('add to timeline when clicking in the barchart legend');
|
||||
|
||||
addToTimelineFromBarchartLegend();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 3);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
|
||||
cy.log('add to timeline when clicking in an indicator flyout overview tab table row');
|
||||
|
||||
openFlyout(0);
|
||||
addToTimelineFromFlyoutOverviewTabTable();
|
||||
closeFlyout();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
|
||||
cy.log('add to timeline when clicking in an indicator flyout overview block');
|
||||
|
||||
openFlyout(0);
|
||||
addToTimelineFromFlyoutOverviewTabBlock();
|
||||
closeFlyout();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
|
||||
cy.log('add to timeline when clicking in an indicator table cell');
|
||||
|
||||
addToTimelineFromTableCell();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 9);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
|
||||
cy.log('investigate in timeline when clicking in an indicator table action row');
|
||||
|
||||
investigateInTimelineFromTable();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
|
||||
cy.log('investigate in timeline when clicking in an indicator flyout');
|
||||
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
investigateInTimelineFromFlyout();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"reporterEnabled": "mochawesome, mocha-junit-reporter, buildkite-test-collector/mocha/reporter",
|
||||
"buildkiteTestCollectorMochaReporterReporterOptions": {
|
||||
"token_name": "BK_ANALYTICS_API_KEY",
|
||||
"follow-symlinks": true,
|
||||
"timeout": 120,
|
||||
"upload-concurrency": 50
|
||||
},
|
||||
"reporterOptions": {
|
||||
"html": false,
|
||||
"json": true,
|
||||
"mochaFile": "../../../target/kibana-threat-intelligence/cypress/results/TEST-threat-intelligence-cypress-[hash].xml",
|
||||
"overwrite": false,
|
||||
"reportDir": "../../../target/kibana-threat-intelligence/cypress/results"
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* 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 { ADD_TO_BLOCK_LIST_TEST_ID as INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_BLOCK_LIST_TEST_ID } from '../../public/modules/indicators/components/flyout/test_ids';
|
||||
import { ADD_TO_BLOCK_LIST_TEST_ID as INDICATORS_TABLE_ADD_TO_BLOCK_LIST_TEST_ID } from '../../public/modules/indicators/components/table/test_ids';
|
||||
|
||||
export const INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON = `[data-test-subj="${INDICATORS_TABLE_ADD_TO_BLOCK_LIST_TEST_ID}"]`;
|
||||
export const FLYOUT_ADD_TO_BLOCK_LIST_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_BLOCK_LIST_TEST_ID}"]`;
|
||||
export const BLOCK_LIST_NAME = `[data-test-subj="blocklist-form-name-input"]`;
|
||||
export const BLOCK_LIST_DESCRIPTION = `[data-test-subj="blocklist-form-description-input"]`;
|
||||
export const BLOCK_LIST_ADD_BUTTON = `[class="eui-textTruncate"]`;
|
||||
export const BLOCK_LIST_TOAST_LIST = `[data-test-subj="globalToastList"]`;
|
||||
export const BLOCK_LIST_VALUE_INPUT = (iocId: string) =>
|
||||
`[data-test-subj="blocklist-form-values-input-${iocId}"]`;
|
||||
export const SAVED_BLOCK_LIST_NAME = `[data-test-subj="blocklistPage-card-header-title"]`;
|
||||
export const SAVED_BLOCK_LIST_DESCRIPTION = `[data-test-subj="blocklistPage-card-description"]`;
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
ADD_TO_EXISTING_CASE_TEST_ID as INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_EXISTING_CASE_TEST_ID,
|
||||
ADD_TO_NEW_CASE_TEST_ID as INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_NEW_CASE_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/flyout/test_ids';
|
||||
import {
|
||||
ADD_TO_EXISTING_TEST_ID as INDICATORS_TABLE_ADD_TO_EXISTING_TEST_ID,
|
||||
ADD_TO_NEW_CASE_TEST_ID as INDICATORS_TABLE_ADD_TO_NEW_CASE_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/table/test_ids';
|
||||
|
||||
export const INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON = `[data-test-subj="${INDICATORS_TABLE_ADD_TO_NEW_CASE_TEST_ID}"]`;
|
||||
export const INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON = `[data-test-subj="${INDICATORS_TABLE_ADD_TO_EXISTING_TEST_ID}"]`;
|
||||
export const FLYOUT_ADD_TO_EXISTING_CASE_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_EXISTING_CASE_TEST_ID}"]`;
|
||||
export const FLYOUT_ADD_TO_NEW_CASE_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_NEW_CASE_TEST_ID}"]`;
|
||||
export const SELECT_EXISTING_CASE = `[class="eui-textTruncate"]`;
|
||||
export const VIEW_CASE_TOASTER_LINK = `[data-test-subj="toaster-content-case-view-link"]`;
|
||||
export const CASE_COMMENT_EXTERNAL_REFERENCE = `[data-test-subj="comment-externalReference-indicator"]`;
|
||||
export const NEW_CASE_NAME_INPUT = `[data-test-subj="input"][aria-describedby="caseTitle"]`;
|
||||
export const NEW_CASE_DESCRIPTION_INPUT = `[data-test-subj="euiMarkdownEditorTextArea"]`;
|
||||
export const NEW_CASE_CREATE_BUTTON = `[data-test-subj="create-case-submit"]`;
|
||||
export const SELECT_CASE_TABLE_ROW = `.euiTableRow`;
|
||||
export const SELECT_EXISTING_CASES_MODAL = `[data-test-subj="all-cases-modal"]`;
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const UPDATE_STATUS = `[data-test-subj="updateStatus"]`;
|
||||
export const SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM = `[data-test-subj="solutionSideNavItemLink-administration"]`;
|
||||
export const SECURITY_SOLUTION_NAVBAR_THREAT_INTELLIGENCE_ITEM = `[data-test-subj="solutionSideNavItemLink-threat_intelligence"]`;
|
||||
export const MANAGE_NAVIGATION_ITEMS = `.euiLink`;
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const EMPTY_PAGE_BODY = '[data-test-subj="tiEmptyPage"]';
|
||||
export const EMPTY_PAGE_DOCS_LINK = '[data-test-subj="tiEmptyPageDocsLink"]';
|
||||
export const EMPTY_PAGE_INTEGRATIONS_LINK = '[data-test-subj="tiEmptyPageIntegrationsPageLink"]';
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Breadcrumbs */
|
||||
|
||||
import { PANEL_TEST_ID, TITLE_TEST_ID } from '../../public/components/test_ids';
|
||||
import { INSPECT_BUTTON_TEST_ID } from '../../public/modules/indicators/hooks/test_ids';
|
||||
import {
|
||||
DROPDOWN_TEST_ID,
|
||||
FILTER_IN_BUTTON_TEST_ID as LEGEND_FILTER_IN_BUTTON_TEST_ID,
|
||||
FILTER_OUT_BUTTON_TEST_ID as LEGEND_FILTER_OUT_BUTTON_TEST_ID,
|
||||
POPOVER_BUTTON_TEST_ID as LEGEND_POPOVER_BUTTON_TEST_ID,
|
||||
TIMELINE_BUTTON_TEST_ID as LEGEND_TIMELINE_BUTTON_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/barchart/test_ids';
|
||||
import {
|
||||
TAKE_ACTION_BUTTON_TEST_ID as INDICATOR_FLYOUT_TAKE_ACTION_TAKE_ACTION_BUTTON_TEST_ID,
|
||||
INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS,
|
||||
INDICATORS_FLYOUT_OVERVIEW_TABLE,
|
||||
CODE_BLOCK_TEST_ID,
|
||||
FLYOUT_TABLE_TEST_ID,
|
||||
INDICATORS_FLYOUT_TABS_TEST_ID,
|
||||
INDICATORS_FLYOUT_TITLE_TEST_ID,
|
||||
FILTER_IN_BUTTON_TEST_ID as VALUE_ACTION_FILTER_IN_BUTTON_TEST_ID,
|
||||
FILTER_OUT_BUTTON_TEST_ID as VALUE_ACTION_FILTER_OUT_BUTTON_TEST_ID,
|
||||
POPOVER_BUTTON_TEST_ID as VALUE_ACTION_POPOVER_BUTTON_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/flyout/test_ids';
|
||||
import {
|
||||
MORE_ACTIONS_TEST_ID as INDICATORS_TABLE_MORE_ACTIONS_TEST_ID,
|
||||
BUTTON_TEST_ID,
|
||||
FILTER_IN_BUTTON_TEST_ID as CELL_FILTER_IN_BUTTON_TEST_ID,
|
||||
FILTER_OUT_BUTTON_TEST_ID as CELL_FILTER_OUT_BUTTON_TEST_ID,
|
||||
TABLE_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/table/test_ids';
|
||||
|
||||
/* Indicators Table */
|
||||
|
||||
export const INDICATORS_TABLE = `[data-test-subj="${TABLE_TEST_ID}"]`;
|
||||
export const INDICATORS_TABLE_ROW_CELL = `[data-test-subj="dataGridRowCell"]`;
|
||||
export const INDICATORS_TABLE_INDICATOR_NAME_CELL = `[data-gridcell-column-id="threat.indicator.name"]`;
|
||||
export const INDICATORS_TABLE_INDICATOR_TYPE_CELL = `[data-gridcell-column-id="threat.indicator.type"]`;
|
||||
export const INDICATORS_TABLE_INDICATOR_NAME_COLUMN_HEADER = `[data-test-subj="dataGridHeaderCell-threat.indicator.name"]`;
|
||||
export const INDICATORS_TABLE_INDICATOR_TYPE_COLUMN_HEADER = `[data-test-subj="dataGridHeaderCell-threat.indicator.type"]`;
|
||||
export const INDICATORS_TABLE_FEED_NAME_COLUMN_HEADER = `[data-test-subj="dataGridHeaderCell-threat.feed.name"]`;
|
||||
export const INDICATORS_TABLE_FIRST_SEEN_COLUMN_HEADER = `[data-test-subj="dataGridHeaderCell-threat.indicator.first_seen"]`;
|
||||
export const INDICATORS_TABLE_LAST_SEEN_COLUMN_HEADER = `[data-test-subj="dataGridHeaderCell-threat.indicator.last_seen"]`;
|
||||
export const TABLE_CONTROLS = `[data-test-subj="dataGridControls"]`;
|
||||
export const INDICATOR_TYPE_CELL = `[role="gridcell"][data-gridcell-column-id="threat.indicator.type"]`;
|
||||
export const INDICATORS_TABLE_CELL_FILTER_IN_BUTTON = `[data-test-subj="${CELL_FILTER_IN_BUTTON_TEST_ID}"] button`;
|
||||
export const INDICATORS_TABLE_CELL_FILTER_OUT_BUTTON = `[data-test-subj="${CELL_FILTER_OUT_BUTTON_TEST_ID}"] button`;
|
||||
export const INDICATORS_TABLE_MORE_ACTION_BUTTON_ICON = `[data-test-subj="${INDICATORS_TABLE_MORE_ACTIONS_TEST_ID}"]`;
|
||||
|
||||
/* Flyout */
|
||||
|
||||
export const TOGGLE_FLYOUT_BUTTON = `[data-test-subj="${BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_CLOSE_BUTTON = `[data-test-subj="euiFlyoutCloseButton"]`;
|
||||
export const FLYOUT_TITLE = `[data-test-subj="${INDICATORS_FLYOUT_TITLE_TEST_ID}"]`;
|
||||
export const FLYOUT_TABS = `[data-test-subj="${INDICATORS_FLYOUT_TABS_TEST_ID}"]`;
|
||||
export const FLYOUT_TABLE = `[data-test-subj="${FLYOUT_TABLE_TEST_ID}"]`;
|
||||
export const FLYOUT_JSON = `[data-test-subj="${CODE_BLOCK_TEST_ID}"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_TABLE_ROW_FILTER_IN_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_TABLE}${VALUE_ACTION_FILTER_IN_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_TABLE_ROW_FILTER_OUT_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_TABLE}${VALUE_ACTION_FILTER_OUT_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_BLOCKS_ITEM = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}Item"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_BLOCKS_FILTER_IN_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}${VALUE_ACTION_FILTER_IN_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_BLOCKS_FILTER_OUT_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}${VALUE_ACTION_FILTER_OUT_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_TABLE_MORE_ACTIONS_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_TABLE}${VALUE_ACTION_POPOVER_BUTTON_TEST_ID}"] button`;
|
||||
export const FLYOUT_BLOCK_MORE_ACTIONS_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}${VALUE_ACTION_POPOVER_BUTTON_TEST_ID}"] button`;
|
||||
export const FLYOUT_TABLE_TAB_ROW_FILTER_IN_BUTTON = `[data-test-subj="${FLYOUT_TABLE_TEST_ID}${VALUE_ACTION_FILTER_IN_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_TABLE_TAB_ROW_FILTER_OUT_BUTTON = `[data-test-subj="${FLYOUT_TABLE_TEST_ID}${VALUE_ACTION_FILTER_OUT_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_TAKE_ACTION_BUTTON = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_TAKE_ACTION_BUTTON_TEST_ID}"]`;
|
||||
|
||||
/* Field selector */
|
||||
|
||||
export const FIELD_SELECTOR = `[data-test-subj="${DROPDOWN_TEST_ID}"]`;
|
||||
export const FIELD_SELECTOR_INPUT = `[data-test-subj="comboBoxInput"]`;
|
||||
export const FIELD_SELECTOR_TOGGLE_BUTTON = `[data-test-subj="comboBoxToggleListButton"]`;
|
||||
export const FIELD_SELECTOR_LIST = `[data-test-subj="comboBoxOptionsList ${DROPDOWN_TEST_ID}-optionsList"]`;
|
||||
|
||||
/* Field browser */
|
||||
|
||||
export const FIELD_BROWSER = `[data-test-subj="show-field-browser"]`;
|
||||
export const FIELD_BROWSER_MODAL = `[data-test-subj="fields-browser-container"]`;
|
||||
|
||||
/* Barchart */
|
||||
|
||||
export const BARCHART_POPOVER_BUTTON = `[data-test-subj="${LEGEND_POPOVER_BUTTON_TEST_ID}"]`;
|
||||
export const BARCHART_TIMELINE_BUTTON = `[data-test-subj="${LEGEND_TIMELINE_BUTTON_TEST_ID}"]`;
|
||||
export const BARCHART_FILTER_IN_BUTTON = `[data-test-subj="${LEGEND_FILTER_IN_BUTTON_TEST_ID}"]`;
|
||||
export const BARCHART_FILTER_OUT_BUTTON = `[data-test-subj="${LEGEND_FILTER_OUT_BUTTON_TEST_ID}"]`;
|
||||
|
||||
/* Miscenalleous */
|
||||
|
||||
export const DEFAULT_LAYOUT_TITLE = `[data-test-subj="${TITLE_TEST_ID}"]`;
|
||||
export const BREADCRUMBS = `[data-test-subj="breadcrumbs"]`;
|
||||
export const LEADING_BREADCRUMB = `[data-test-subj="breadcrumb first"]`;
|
||||
export const ENDING_BREADCRUMB = `[data-test-subj="breadcrumb last"]`;
|
||||
export const FILTERS_GLOBAL_CONTAINER = `[data-test-subj="filters-global-container"]`;
|
||||
export const TIME_RANGE_PICKER = `[data-test-subj="superDatePickerToggleQuickMenuButton"]`;
|
||||
export const QUERY_INPUT = `[data-test-subj="queryInput"]`;
|
||||
export const EMPTY_STATE = `[data-test-subj="${PANEL_TEST_ID}"]`;
|
||||
export const INSPECTOR_BUTTON = `[data-test-subj="${INSPECT_BUTTON_TEST_ID}"]`;
|
||||
export const INSPECTOR_PANEL = `[data-test-subj="inspectorPanel"]`;
|
||||
export const ADD_INTEGRATIONS_BUTTON = `[data-test-subj="add-data"]`;
|
||||
export const REFRESH_BUTTON = `[data-test-subj="querySubmitButton"]`;
|
||||
export const ADDED_TO_TIMELINE_TOAST = `[data-test-subj="add-to-timeline-toast-success"]`;
|
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const QUERY_BAR = '[data-test-subj="globalDatePicker"]';
|
||||
export const QUERY_BAR_MENU = '[data-test-subj="showQueryBarMenu"]';
|
||||
export const QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON =
|
||||
'[data-test-subj="filter-sets-removeAllFilters"]';
|
||||
export const KQL_FILTER = `[id="popoverFor_filter0"]`;
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS,
|
||||
INDICATORS_FLYOUT_OVERVIEW_TABLE,
|
||||
INVESTIGATE_IN_TIMELINE_TEST_ID as INDICATOR_FLYOUT_TAKE_ACTION_INVESTIGATE_IN_TIMELINE_TEST_ID,
|
||||
TIMELINE_BUTTON_TEST_ID as VALUE_ACTION_TIMELINE_BUTTON_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/flyout/test_ids';
|
||||
import {
|
||||
INVESTIGATE_IN_TIMELINE_TEST_ID as CELL_INVESTIGATE_IN_TIMELINE_TEST_ID,
|
||||
TIMELINE_BUTTON_TEST_ID as CELL_TIMELINE_BUTTON_TEST_ID,
|
||||
} from '../../public/modules/indicators/components/table/test_ids';
|
||||
|
||||
export const INDICATORS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_ICON = `[data-test-subj="${CELL_INVESTIGATE_IN_TIMELINE_TEST_ID}"]`;
|
||||
export const UNTITLED_TIMELINE_BUTTON = `[data-test-subj="timeline-bottom-bar-title-button"]`;
|
||||
export const INDICATORS_TABLE_CELL_TIMELINE_BUTTON = `[data-test-subj="${CELL_TIMELINE_BUTTON_TEST_ID}"] button`;
|
||||
export const TIMELINE_DATA_PROVIDERS_WRAPPER = `[data-test-subj="dataProviders"]`;
|
||||
export const TIMELINE_DRAGGABLE_ITEM = `[data-test-subj="providerContainer"]`;
|
||||
export const TIMELINE_AND_OR_BADGE = `[data-test-subj="and-or-badge"]`;
|
||||
export const CLOSE_TIMELINE_BTN = '[data-test-subj="timeline-modal-header-close-button"]';
|
||||
export const FLYOUT_OVERVIEW_TAB_TABLE_ROW_TIMELINE_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_TABLE}${VALUE_ACTION_TIMELINE_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_BLOCKS_TIMELINE_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}${VALUE_ACTION_TIMELINE_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_INVESTIGATE_IN_TIMELINE_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_INVESTIGATE_IN_TIMELINE_TEST_ID}"]`;
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
Cypress.on('uncaught:exception', () => {
|
||||
return false;
|
||||
});
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
BLOCK_LIST_ADD_BUTTON,
|
||||
BLOCK_LIST_DESCRIPTION,
|
||||
BLOCK_LIST_NAME,
|
||||
BLOCK_LIST_TOAST_LIST,
|
||||
FLYOUT_ADD_TO_BLOCK_LIST_ITEM,
|
||||
INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON,
|
||||
} from '../screens/blocklist';
|
||||
|
||||
/**
|
||||
* Open the blocklist form from the indicators table more actions menu
|
||||
*/
|
||||
export const openAddToBlockListFlyoutFromTable = () => {
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the blocklist form from the indicators flyout take action menu
|
||||
*/
|
||||
export const openAddToBlocklistFromFlyout = () => {
|
||||
cy.get(FLYOUT_ADD_TO_BLOCK_LIST_ITEM).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill out blocklist form with title and description
|
||||
*/
|
||||
export const fillBlocklistForm = (title: string, description: string) => {
|
||||
cy.get(BLOCK_LIST_NAME).type(title);
|
||||
cy.get(BLOCK_LIST_DESCRIPTION).type(description);
|
||||
cy.get(BLOCK_LIST_ADD_BUTTON).last().click();
|
||||
|
||||
const text: string = `"${title}" has been added`;
|
||||
cy.get(BLOCK_LIST_TOAST_LIST).should('exist').and('contain.text', text);
|
||||
};
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
FLYOUT_ADD_TO_EXISTING_CASE_ITEM,
|
||||
FLYOUT_ADD_TO_NEW_CASE_ITEM,
|
||||
INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON,
|
||||
INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON,
|
||||
NEW_CASE_CREATE_BUTTON,
|
||||
NEW_CASE_DESCRIPTION_INPUT,
|
||||
NEW_CASE_NAME_INPUT,
|
||||
SELECT_CASE_TABLE_ROW,
|
||||
SELECT_EXISTING_CASE,
|
||||
SELECT_EXISTING_CASES_MODAL,
|
||||
VIEW_CASE_TOASTER_LINK,
|
||||
} from '../screens/cases';
|
||||
|
||||
/**
|
||||
* Open the add to new case flyout from the indicators table more actions menu
|
||||
*/
|
||||
export const openAddToNewCaseFlyoutFromTable = () => {
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the add to existing case flyout from the indicators table more actions menu
|
||||
*/
|
||||
export const openAddToExistingCaseFlyoutFromTable = () => {
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the new case flyout from the indicators flyout take action menu
|
||||
*/
|
||||
export const openAddToNewCaseFromFlyout = () => {
|
||||
cy.get(FLYOUT_ADD_TO_NEW_CASE_ITEM).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the new existing flyout from the indicators flyout take action menu
|
||||
*/
|
||||
export const openAddToExistingCaseFromFlyout = () => {
|
||||
cy.get(FLYOUT_ADD_TO_EXISTING_CASE_ITEM).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new case from the Threat Intelligence page
|
||||
*/
|
||||
export const createNewCaseFromTI = () => {
|
||||
cy.get(NEW_CASE_NAME_INPUT).type('case');
|
||||
cy.get(NEW_CASE_DESCRIPTION_INPUT).type('case description');
|
||||
cy.get(NEW_CASE_CREATE_BUTTON).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Click on the toaster to navigate to case and verified created case
|
||||
*/
|
||||
export const navigateToCaseViaToaster = () => {
|
||||
cy.get(VIEW_CASE_TOASTER_LINK).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Select existing case from cases modal
|
||||
*/
|
||||
export const selectExistingCase = () => {
|
||||
cy.get(SELECT_EXISTING_CASES_MODAL).within(() => {
|
||||
cy.get(SELECT_CASE_TABLE_ROW).its('length').should('be.gte', 0);
|
||||
cy.get(SELECT_EXISTING_CASE).should('exist').contains('Select').click();
|
||||
});
|
||||
};
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
MANAGE_NAVIGATION_ITEMS,
|
||||
SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM,
|
||||
SECURITY_SOLUTION_NAVBAR_THREAT_INTELLIGENCE_ITEM,
|
||||
UPDATE_STATUS,
|
||||
} from '../screens/common';
|
||||
|
||||
import {
|
||||
BARCHART_POPOVER_BUTTON,
|
||||
FLYOUT_CLOSE_BUTTON,
|
||||
FLYOUT_TABS,
|
||||
FLYOUT_TAKE_ACTION_BUTTON,
|
||||
INDICATORS_TABLE_MORE_ACTION_BUTTON_ICON,
|
||||
TOGGLE_FLYOUT_BUTTON,
|
||||
} from '../screens/indicators';
|
||||
|
||||
/**
|
||||
* Navigate to Blocklist screen via the Security Solution navbar and Manage menu item
|
||||
*/
|
||||
export const navigateToBlocklist = () => {
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM).scrollIntoView();
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM).click();
|
||||
cy.get(MANAGE_NAVIGATION_ITEMS).contains('Blocklist').click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigate to Threat Intelligence screen via the Security Solution navbar
|
||||
*/
|
||||
export const navigateToThreatIntelligence = () => {
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_THREAT_INTELLIGENCE_ITEM).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the opened flyout
|
||||
*/
|
||||
export const closeFlyout = () => {
|
||||
cy.get(FLYOUT_CLOSE_BUTTON).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the indicators table more actions menu
|
||||
*/
|
||||
export const openIndicatorsTableMoreActions = (index: number) => {
|
||||
cy.get(INDICATORS_TABLE_MORE_ACTION_BUTTON_ICON).eq(index).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the indicator flyout from indicators table
|
||||
*/
|
||||
export const openFlyout = (index: number) => {
|
||||
cy.get(TOGGLE_FLYOUT_BUTTON).eq(index).click({ force: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the take action button within indicator flyout
|
||||
*/
|
||||
export const openFlyoutTakeAction = () => {
|
||||
cy.get(FLYOUT_TAKE_ACTION_BUTTON).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigate to Table tab in indicators flyout
|
||||
*/
|
||||
export const navigateToFlyoutTableTab = () => {
|
||||
cy.get(`${FLYOUT_TABS} button:nth-child(2)`).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigate to Json tab in indicators flyout
|
||||
*/
|
||||
export const navigateToFlyoutJsonTab = () => {
|
||||
cy.get(`${FLYOUT_TABS} button:nth-child(3)`).click();
|
||||
};
|
||||
|
||||
export const waitForViewToBeUpdated = () => {
|
||||
cy.get(UPDATE_STATUS).scrollIntoView();
|
||||
cy.get(UPDATE_STATUS).should('contain.text', 'Updated');
|
||||
};
|
||||
|
||||
/**
|
||||
* Open barchart 3-dot popover menu
|
||||
*/
|
||||
export const openBarchartPopoverMenu = () => {
|
||||
cy.get(BARCHART_POPOVER_BUTTON).first().scrollIntoView();
|
||||
cy.get(BARCHART_POPOVER_BUTTON).should('exist').first().click();
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* 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 Path from 'path';
|
||||
|
||||
const ES_ARCHIVE_DIR = '../../test/threat_intelligence_cypress/es_archives';
|
||||
const CONFIG_PATH = '../../test/functional/config.base.js';
|
||||
const ES_URL = Cypress.env('ELASTICSEARCH_URL');
|
||||
const KIBANA_URL = Cypress.config().baseUrl;
|
||||
|
||||
// Otherwise cy.exec would inject NODE_TLS_REJECT_UNAUTHORIZED=0 and node would abort if used over https
|
||||
const NODE_TLS_REJECT_UNAUTHORIZED = '1';
|
||||
|
||||
export const esArchiverLoad = (folder: string) => {
|
||||
const path = Path.join(ES_ARCHIVE_DIR, folder);
|
||||
cy.exec(
|
||||
`node ../../../scripts/es_archiver load "${path}" --config "${CONFIG_PATH}" --es-url "${ES_URL}" --kibana-url "${KIBANA_URL}"`,
|
||||
{ env: { NODE_TLS_REJECT_UNAUTHORIZED } }
|
||||
);
|
||||
};
|
||||
|
||||
export const esArchiverUnload = (folder: string) => {
|
||||
const path = Path.join(ES_ARCHIVE_DIR, folder);
|
||||
cy.exec(
|
||||
`node ../../../scripts/es_archiver unload "${path}" --config "${CONFIG_PATH}" --es-url "${ES_URL}" --kibana-url "${KIBANA_URL}"`,
|
||||
{ env: { NODE_TLS_REJECT_UNAUTHORIZED } }
|
||||
);
|
||||
};
|
||||
|
||||
export const esArchiverResetKibana = () => {
|
||||
cy.exec(
|
||||
`node ../../../scripts/es_archiver empty-kibana-index --config "${CONFIG_PATH}" --es-url "${ES_URL}" --kibana-url "${KIBANA_URL}"`,
|
||||
{ env: { NODE_TLS_REJECT_UNAUTHORIZED }, failOnNonZeroExit: false }
|
||||
);
|
||||
};
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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 { QUERY_INPUT } from '../screens/indicators';
|
||||
|
||||
/**
|
||||
* Navigate to specific page in indicators table
|
||||
*/
|
||||
export const navigateToIndicatorsTablePage = (index: number) => {
|
||||
cy.get(`[data-test-subj="pagination-button-${index}"]`).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears text in KQL bar
|
||||
*/
|
||||
export const enterQuery = (text: string) => {
|
||||
cy.get(QUERY_INPUT).should('exist').focus();
|
||||
cy.get(QUERY_INPUT).should('exist').type(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears text in KQL bar
|
||||
*/
|
||||
export const clearQuery = () => {
|
||||
cy.get(QUERY_INPUT).should('exist').focus();
|
||||
cy.get(QUERY_INPUT).should('exist').clear();
|
||||
};
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* 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 type { UrlObject } from 'url';
|
||||
import Url from 'url';
|
||||
|
||||
import * as yaml from 'js-yaml';
|
||||
|
||||
import { encode } from '@kbn/rison';
|
||||
import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '@kbn/security-solution-plugin/common/constants';
|
||||
import {
|
||||
LOADING_INDICATOR,
|
||||
LOADING_INDICATOR_HIDDEN,
|
||||
} from '@kbn/test-suites-xpack/security_solution_cypress/cypress/screens/security_header';
|
||||
import type { ROLES } from './privileges';
|
||||
|
||||
const LOGIN_API_ENDPOINT = '/internal/security/login';
|
||||
|
||||
/**
|
||||
* Credentials in the `kibana.dev.yml` config file will be used to authenticate
|
||||
* with Kibana when credentials are not provided via environment variables
|
||||
*/
|
||||
const KIBANA_DEV_YML_PATH = '../../../config/kibana.dev.yml';
|
||||
|
||||
/**
|
||||
* The configuration path in `kibana.dev.yml` to the username to be used when
|
||||
* authenticating with Kibana.
|
||||
*/
|
||||
const ELASTICSEARCH_USERNAME_CONFIG_PATH = 'config.elasticsearch.username';
|
||||
|
||||
/**
|
||||
* The configuration path in `kibana.dev.yml` to the password to be used when
|
||||
* authenticating with Kibana.
|
||||
*/
|
||||
const ELASTICSEARCH_PASSWORD_CONFIG_PATH = 'config.elasticsearch.password';
|
||||
|
||||
/**
|
||||
* The `CYPRESS_ELASTICSEARCH_USERNAME` environment variable specifies the
|
||||
* username to be used when authenticating with Kibana
|
||||
*/
|
||||
const ELASTICSEARCH_USERNAME = 'ELASTICSEARCH_USERNAME';
|
||||
|
||||
/**
|
||||
* The `CYPRESS_ELASTICSEARCH_PASSWORD` environment variable specifies the
|
||||
* username to be used when authenticating with Kibana
|
||||
*/
|
||||
const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD';
|
||||
|
||||
/**
|
||||
* cy.visit will default to the baseUrl which uses the default kibana test user
|
||||
* This function will override that functionality in cy.visit by building the baseUrl
|
||||
* directly from the environment variables set up in x-pack/test/security_solution_cypress/runner.ts
|
||||
*
|
||||
* @param role string role/user to log in with
|
||||
* @param route string route to visit
|
||||
*/
|
||||
export const getUrlWithRoute = (role: ROLES, route: string) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
const kibana = new URL(String(url));
|
||||
const theUrl = `${Url.format({
|
||||
auth: `${role}:changeme`,
|
||||
username: role,
|
||||
password: 'changeme',
|
||||
protocol: kibana.protocol.replace(':', ''),
|
||||
hostname: kibana.hostname,
|
||||
port: kibana.port,
|
||||
} as UrlObject)}${route.startsWith('/') ? '' : '/'}${route}`;
|
||||
cy.log(`origin: ${theUrl}`);
|
||||
return theUrl;
|
||||
};
|
||||
|
||||
interface User {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a URL with basic auth using the passed in user.
|
||||
*
|
||||
* @param user the user information to build the basic auth with
|
||||
* @param route string route to visit
|
||||
*/
|
||||
export const constructUrlWithUser = (user: User, route: string) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
const kibana = new URL(String(url));
|
||||
const hostname = kibana.hostname;
|
||||
const username = user.username;
|
||||
const password = user.password;
|
||||
const protocol = kibana.protocol.replace(':', '');
|
||||
const port = kibana.port;
|
||||
|
||||
const path = `${route.startsWith('/') ? '' : '/'}${route}`;
|
||||
const strUrl = `${protocol}://${username}:${password}@${hostname}:${port}${path}`;
|
||||
const builtUrl = new URL(strUrl);
|
||||
|
||||
cy.log(`origin: ${builtUrl.href}`);
|
||||
return builtUrl.href;
|
||||
};
|
||||
|
||||
export const getCurlScriptEnvVars = () => ({
|
||||
ELASTICSEARCH_URL: Cypress.env('ELASTICSEARCH_URL'),
|
||||
ELASTICSEARCH_USERNAME: Cypress.env('ELASTICSEARCH_USERNAME'),
|
||||
ELASTICSEARCH_PASSWORD: Cypress.env('ELASTICSEARCH_PASSWORD'),
|
||||
KIBANA_URL: Cypress.config().baseUrl,
|
||||
});
|
||||
|
||||
export const postRoleAndUser = (role: ROLES) => {
|
||||
const env = getCurlScriptEnvVars();
|
||||
const detectionsRoleScriptPath = `./server/lib/detection_engine/scripts/roles_users/${role}/post_detections_role.sh`;
|
||||
const detectionsRoleJsonPath = `./server/lib/detection_engine/scripts/roles_users/${role}/detections_role.json`;
|
||||
const detectionsUserScriptPath = `./server/lib/detection_engine/scripts/roles_users/${role}/post_detections_user.sh`;
|
||||
const detectionsUserJsonPath = `./server/lib/detection_engine/scripts/roles_users/${role}/detections_user.json`;
|
||||
|
||||
// post the role
|
||||
cy.exec(`bash ${detectionsRoleScriptPath} ${detectionsRoleJsonPath}`, {
|
||||
env,
|
||||
});
|
||||
|
||||
// post the user associated with the role to elasticsearch
|
||||
cy.exec(`bash ${detectionsUserScriptPath} ${detectionsUserJsonPath}`, {
|
||||
env,
|
||||
});
|
||||
};
|
||||
|
||||
export const loginWithRole = async (role: ROLES) => {
|
||||
postRoleAndUser(role);
|
||||
const theUrl = Url.format({
|
||||
auth: `${role}:changeme`,
|
||||
username: role,
|
||||
password: 'changeme',
|
||||
protocol: Cypress.env('protocol'),
|
||||
hostname: Cypress.env('hostname'),
|
||||
port: Cypress.env('configport'),
|
||||
} as UrlObject);
|
||||
cy.log(`origin: ${theUrl}`);
|
||||
cy.session(role, () => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username: role,
|
||||
password: 'changeme',
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: getUrlWithRoute(role, LOGIN_API_ENDPOINT),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana using, if specified, credentials specified by
|
||||
* environment variables. The credentials in `kibana.dev.yml` will be used
|
||||
* for authentication when the environment variables are unset.
|
||||
*
|
||||
* To speed the execution of tests, prefer this non-interactive authentication,
|
||||
* which is faster than authentication via Kibana's interactive login page.
|
||||
*/
|
||||
export const login = (role?: ROLES) => {
|
||||
if (role != null) {
|
||||
loginWithRole(role);
|
||||
} else if (credentialsProvidedByEnvironment()) {
|
||||
loginViaEnvironmentCredentials();
|
||||
} else {
|
||||
loginViaConfig();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns `true` if the credentials used to login to Kibana are provided
|
||||
* via environment variables
|
||||
*/
|
||||
const credentialsProvidedByEnvironment = (): boolean =>
|
||||
Cypress.env(ELASTICSEARCH_USERNAME) != null && Cypress.env(ELASTICSEARCH_PASSWORD) != null;
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana by reading credentials from the
|
||||
* `CYPRESS_ELASTICSEARCH_USERNAME` and `CYPRESS_ELASTICSEARCH_PASSWORD`
|
||||
* environment variables, and POSTing the username and password directly to
|
||||
* Kibana's `/internal/security/login` endpoint, bypassing the login page (for speed).
|
||||
*/
|
||||
const loginViaEnvironmentCredentials = () => {
|
||||
cy.log(
|
||||
`Authenticating via environment credentials from the \`CYPRESS_${ELASTICSEARCH_USERNAME}\` and \`CYPRESS_${ELASTICSEARCH_PASSWORD}\` environment variables`
|
||||
);
|
||||
|
||||
const username = Cypress.env(ELASTICSEARCH_USERNAME);
|
||||
const password = Cypress.env(ELASTICSEARCH_PASSWORD);
|
||||
|
||||
// programmatically authenticate without interacting with the Kibana login page
|
||||
cy.session([username, password], () => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-env' },
|
||||
method: 'POST',
|
||||
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana by reading credentials from the
|
||||
* `kibana.dev.yml` file and POSTing the username and password directly to
|
||||
* Kibana's `/internal/security/login` endpoint, bypassing the login page (for speed).
|
||||
*/
|
||||
const loginViaConfig = () => {
|
||||
cy.log(
|
||||
`Authenticating via config credentials \`${ELASTICSEARCH_USERNAME_CONFIG_PATH}\` and \`${ELASTICSEARCH_PASSWORD_CONFIG_PATH}\` from \`${KIBANA_DEV_YML_PATH}\``
|
||||
);
|
||||
|
||||
// read the login details from `kibana.dev.yaml`
|
||||
cy.readFile(KIBANA_DEV_YML_PATH).then((kibanaDevYml) => {
|
||||
const config = yaml.safeLoad(kibanaDevYml);
|
||||
|
||||
const username = config.elasticsearch.username;
|
||||
const password = config.elasticsearch.password;
|
||||
|
||||
// programmatically authenticate without interacting with the Kibana login page
|
||||
cy.session([username, password], () => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the configured auth details that were used to spawn cypress
|
||||
*
|
||||
* @returns the default Elasticsearch username and password for this environment
|
||||
*/
|
||||
export const getEnvAuth = (): User => {
|
||||
if (credentialsProvidedByEnvironment()) {
|
||||
return {
|
||||
username: Cypress.env(ELASTICSEARCH_USERNAME),
|
||||
password: Cypress.env(ELASTICSEARCH_PASSWORD),
|
||||
};
|
||||
} else {
|
||||
let user: User = { username: '', password: '' };
|
||||
cy.readFile(KIBANA_DEV_YML_PATH).then((devYml) => {
|
||||
const config = yaml.safeLoad(devYml);
|
||||
user = { username: config.elasticsearch.username, password: config.elasticsearch.password };
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
};
|
||||
|
||||
export const visit = (url: string, options: Partial<Cypress.VisitOptions> = {}, role?: ROLES) => {
|
||||
const timerangeConfig = {
|
||||
from: 1547914976217,
|
||||
fromStr: '2019-01-19T16:22:56.217Z',
|
||||
kind: 'relative',
|
||||
to: 1579537385745,
|
||||
toStr: 'now',
|
||||
};
|
||||
|
||||
const timerange = encode({
|
||||
global: {
|
||||
linkTo: ['timeline'],
|
||||
timerange: timerangeConfig,
|
||||
},
|
||||
timeline: {
|
||||
linkTo: ['global'],
|
||||
timerange: timerangeConfig,
|
||||
},
|
||||
});
|
||||
|
||||
cy.visit(role ? getUrlWithRoute(role, url) : url, {
|
||||
...options,
|
||||
qs: {
|
||||
...options.qs,
|
||||
timerange,
|
||||
},
|
||||
onBeforeLoad: (win) => {
|
||||
options.onBeforeLoad?.(win);
|
||||
|
||||
disableNewFeaturesTours(win);
|
||||
},
|
||||
});
|
||||
waitForPageToBeLoaded();
|
||||
};
|
||||
|
||||
const disableNewFeaturesTours = (window: Window) => {
|
||||
const tourStorageKeys = Object.values(NEW_FEATURES_TOUR_STORAGE_KEYS);
|
||||
const tourConfig = {
|
||||
isTourActive: false,
|
||||
};
|
||||
|
||||
tourStorageKeys.forEach((key) => {
|
||||
window.localStorage.setItem(key, JSON.stringify(tourConfig));
|
||||
});
|
||||
};
|
||||
|
||||
export const waitForPageToBeLoaded = () => {
|
||||
cy.get(LOADING_INDICATOR_HIDDEN).should('exist');
|
||||
cy.get(LOADING_INDICATOR).should('not.exist');
|
||||
};
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* 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 { constructUrlWithUser, getEnvAuth } from './login';
|
||||
|
||||
interface User {
|
||||
username: string;
|
||||
password: string;
|
||||
description?: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
username: string;
|
||||
full_name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
interface FeaturesPrivileges {
|
||||
[featureId: string]: string[];
|
||||
}
|
||||
|
||||
interface ElasticsearchIndices {
|
||||
names: string[];
|
||||
privileges: string[];
|
||||
}
|
||||
|
||||
interface ElasticSearchPrivilege {
|
||||
cluster?: string[];
|
||||
indices?: ElasticsearchIndices[];
|
||||
}
|
||||
|
||||
interface KibanaPrivilege {
|
||||
spaces: string[];
|
||||
base?: string[];
|
||||
feature?: FeaturesPrivileges;
|
||||
}
|
||||
|
||||
interface Role {
|
||||
name: string;
|
||||
privileges: {
|
||||
elasticsearch?: ElasticSearchPrivilege;
|
||||
kibana?: KibanaPrivilege[];
|
||||
};
|
||||
}
|
||||
|
||||
const getUserInfo = (user: User): UserInfo => ({
|
||||
username: user.username,
|
||||
full_name: user.username.replace('_', ' '),
|
||||
email: `${user.username}@elastic.co`,
|
||||
});
|
||||
|
||||
export enum ROLES {
|
||||
elastic = 'elastic',
|
||||
}
|
||||
|
||||
export const createUsersAndRoles = (users: User[], roles: Role[]) => {
|
||||
const envUser = getEnvAuth();
|
||||
for (const role of roles) {
|
||||
cy.log(`Creating role: ${JSON.stringify(role)}`);
|
||||
cy.request({
|
||||
body: role.privileges,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'PUT',
|
||||
url: constructUrlWithUser(envUser, `/api/security/role/${role.name}`),
|
||||
})
|
||||
.its('status')
|
||||
.should('eql', 204);
|
||||
}
|
||||
|
||||
for (const user of users) {
|
||||
const userInfo = getUserInfo(user);
|
||||
cy.log(`Creating user: ${JSON.stringify(user)}`);
|
||||
cy.request({
|
||||
body: {
|
||||
username: user.username,
|
||||
password: user.password,
|
||||
roles: user.roles,
|
||||
full_name: userInfo.full_name,
|
||||
email: userInfo.email,
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: constructUrlWithUser(envUser, `/internal/security/users/${user.username}`),
|
||||
})
|
||||
.its('status')
|
||||
.should('eql', 200);
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteUsersAndRoles = (users: User[], roles: Role[]) => {
|
||||
const envUser = getEnvAuth();
|
||||
for (const user of users) {
|
||||
cy.log(`Deleting user: ${JSON.stringify(user)}`);
|
||||
cy.request({
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'DELETE',
|
||||
url: constructUrlWithUser(envUser, `/internal/security/users/${user.username}`),
|
||||
failOnStatusCode: false,
|
||||
})
|
||||
.its('status')
|
||||
.should('oneOf', [204, 404]);
|
||||
}
|
||||
|
||||
for (const role of roles) {
|
||||
cy.log(`Deleting role: ${JSON.stringify(role)}`);
|
||||
cy.request({
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'DELETE',
|
||||
url: constructUrlWithUser(envUser, `/api/security/role/${role.name}`),
|
||||
failOnStatusCode: false,
|
||||
})
|
||||
.its('status')
|
||||
.should('oneOf', [204, 404]);
|
||||
}
|
||||
};
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* 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 { openBarchartPopoverMenu } from './common';
|
||||
import {
|
||||
QUERY_BAR,
|
||||
QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON,
|
||||
QUERY_BAR_MENU,
|
||||
} from '../screens/query_bar';
|
||||
import {
|
||||
BARCHART_FILTER_IN_BUTTON,
|
||||
BARCHART_FILTER_OUT_BUTTON,
|
||||
INDICATORS_TABLE_CELL_FILTER_IN_BUTTON,
|
||||
INDICATORS_TABLE_CELL_FILTER_OUT_BUTTON,
|
||||
INDICATOR_TYPE_CELL,
|
||||
FLYOUT_OVERVIEW_TAB_BLOCKS_ITEM,
|
||||
FLYOUT_OVERVIEW_TAB_BLOCKS_FILTER_IN_BUTTON,
|
||||
FLYOUT_OVERVIEW_TAB_BLOCKS_FILTER_OUT_BUTTON,
|
||||
FLYOUT_OVERVIEW_TAB_TABLE_ROW_FILTER_IN_BUTTON,
|
||||
FLYOUT_OVERVIEW_TAB_TABLE_ROW_FILTER_OUT_BUTTON,
|
||||
FLYOUT_TABLE_TAB_ROW_FILTER_IN_BUTTON,
|
||||
FLYOUT_TABLE_TAB_ROW_FILTER_OUT_BUTTON,
|
||||
} from '../screens/indicators';
|
||||
|
||||
/**
|
||||
* Filter in value by clicking on the menu item within barchart popover
|
||||
*/
|
||||
export const filterInFromBarChartLegend = () => {
|
||||
openBarchartPopoverMenu();
|
||||
cy.get(BARCHART_FILTER_IN_BUTTON).should('exist').click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out value by clicking on the menu item within barchart popover
|
||||
*/
|
||||
export const filterOutFromBarChartLegend = () => {
|
||||
openBarchartPopoverMenu();
|
||||
cy.get(BARCHART_FILTER_OUT_BUTTON).should('exist').click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter in value by clicking on the menu item within an indicators table cell
|
||||
*/
|
||||
export const filterInFromTableCell = () => {
|
||||
cy.get(INDICATOR_TYPE_CELL).first().should('be.visible');
|
||||
cy.get(INDICATOR_TYPE_CELL).first().trigger('mouseover');
|
||||
cy.get(INDICATOR_TYPE_CELL)
|
||||
.first()
|
||||
.within((_cell) => {
|
||||
cy.get(INDICATORS_TABLE_CELL_FILTER_IN_BUTTON).should('exist').click({
|
||||
force: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out value by clicking on the menu item within an indicators table cell
|
||||
*/
|
||||
export const filterOutFromTableCell = () => {
|
||||
cy.get(INDICATOR_TYPE_CELL).first().trigger('mouseover');
|
||||
cy.get(INDICATOR_TYPE_CELL)
|
||||
.first()
|
||||
.within((_cell) => {
|
||||
cy.get(INDICATORS_TABLE_CELL_FILTER_OUT_BUTTON).should('exist').click({ force: true });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears all filters within KQL bar
|
||||
*/
|
||||
export const clearKQLBar = () => {
|
||||
cy.get(QUERY_BAR).scrollIntoView();
|
||||
cy.get(QUERY_BAR).within(() => cy.get(QUERY_BAR_MENU).click());
|
||||
|
||||
cy.get(QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON).scrollIntoView();
|
||||
cy.get(QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter in value from indicators flyout block item
|
||||
*/
|
||||
export const filterInFromFlyoutBlockItem = () => {
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_ITEM).first().trigger('mouseover');
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_FILTER_IN_BUTTON)
|
||||
.should('exist')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out value from indicators flyout block item
|
||||
*/
|
||||
export const filterOutFromFlyoutBlockItem = () => {
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_ITEM).first().trigger('mouseover');
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_FILTER_OUT_BUTTON)
|
||||
.should('exist')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter in value from indicators flyout overview tab table
|
||||
*/
|
||||
export const filterInFromFlyoutOverviewTable = () => {
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_TABLE_ROW_FILTER_IN_BUTTON).should('exist').first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out value from indicators flyout overview tab table
|
||||
*/
|
||||
export const filterOutFromFlyoutOverviewTable = () => {
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_TABLE_ROW_FILTER_OUT_BUTTON).should('exist').first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter in value from indicators flyout overview tab table
|
||||
*/
|
||||
export const filterInFromFlyoutTableTab = () => {
|
||||
cy.get(FLYOUT_TABLE_TAB_ROW_FILTER_IN_BUTTON).should('exist').first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out value from indicators flyout overview tab table
|
||||
*/
|
||||
export const filterOutFromFlyoutTableTab = () => {
|
||||
cy.get(FLYOUT_TABLE_TAB_ROW_FILTER_OUT_BUTTON).should('exist').first().click();
|
||||
};
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* 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 { recurse } from 'cypress-recurse';
|
||||
import { openBarchartPopoverMenu } from './common';
|
||||
import {
|
||||
CLOSE_TIMELINE_BTN,
|
||||
FLYOUT_INVESTIGATE_IN_TIMELINE_ITEM,
|
||||
FLYOUT_OVERVIEW_TAB_BLOCKS_TIMELINE_BUTTON,
|
||||
FLYOUT_OVERVIEW_TAB_TABLE_ROW_TIMELINE_BUTTON,
|
||||
INDICATORS_TABLE_CELL_TIMELINE_BUTTON,
|
||||
INDICATORS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_ICON,
|
||||
UNTITLED_TIMELINE_BUTTON,
|
||||
} from '../screens/timeline';
|
||||
import {
|
||||
ADDED_TO_TIMELINE_TOAST,
|
||||
BARCHART_TIMELINE_BUTTON,
|
||||
FLYOUT_BLOCK_MORE_ACTIONS_BUTTON,
|
||||
FLYOUT_TABLE_MORE_ACTIONS_BUTTON,
|
||||
INDICATOR_TYPE_CELL,
|
||||
} from '../screens/indicators';
|
||||
|
||||
/**
|
||||
* Add data to timeline from barchart legend menu item
|
||||
*/
|
||||
export const addToTimelineFromBarchartLegend = () => {
|
||||
recurse(
|
||||
() => {
|
||||
openBarchartPopoverMenu();
|
||||
cy.get(BARCHART_TIMELINE_BUTTON).first().click();
|
||||
openBarchartPopoverMenu();
|
||||
return cy.get(ADDED_TO_TIMELINE_TOAST).should(Cypress._.noop);
|
||||
},
|
||||
($el) => !!$el.length
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Add data to timeline from indicators table cell menu
|
||||
*/
|
||||
export const addToTimelineFromTableCell = () => {
|
||||
cy.get(INDICATOR_TYPE_CELL).first().trigger('mouseover');
|
||||
cy.get(INDICATORS_TABLE_CELL_TIMELINE_BUTTON).should('exist').first().click({ force: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Open untitled timeline from button in footerx
|
||||
*/
|
||||
export const openTimeline = () => {
|
||||
cy.get(UNTITLED_TIMELINE_BUTTON).should('exist').first().click({ force: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Close flyout button in top right corner
|
||||
*/
|
||||
export const closeTimeline = () => {
|
||||
cy.get(CLOSE_TIMELINE_BTN).should('be.visible').click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Add data to timeline from flyout overview tab table
|
||||
*/
|
||||
export const addToTimelineFromFlyoutOverviewTabTable = () => {
|
||||
recurse(
|
||||
() => {
|
||||
cy.get(FLYOUT_TABLE_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_TABLE_ROW_TIMELINE_BUTTON).first().click();
|
||||
cy.get(FLYOUT_TABLE_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
|
||||
return cy.get(ADDED_TO_TIMELINE_TOAST).should(Cypress._.noop);
|
||||
},
|
||||
($el) => !!$el.length
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add data to timeline from flyout overview tab block
|
||||
*/
|
||||
export const addToTimelineFromFlyoutOverviewTabBlock = () => {
|
||||
recurse(
|
||||
() => {
|
||||
cy.get(FLYOUT_BLOCK_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_TIMELINE_BUTTON).first().click();
|
||||
cy.get(FLYOUT_BLOCK_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
|
||||
return cy.get(ADDED_TO_TIMELINE_TOAST).should(Cypress._.noop);
|
||||
},
|
||||
($el) => !!$el.length
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Investigate data to timeline from indicators table row
|
||||
*/
|
||||
export const investigateInTimelineFromTable = () => {
|
||||
cy.get(INDICATORS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_ICON).should('exist').first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Investigate data to timeline from flyout take action button
|
||||
*/
|
||||
export const investigateInTimelineFromFlyout = () => {
|
||||
cy.get(FLYOUT_INVESTIGATE_IN_TIMELINE_ITEM).should('exist').first().click();
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"include": ["**/*", "fixtures/**/*.json"],
|
||||
"exclude": ["target/**/*"],
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
"types": ["cypress", "cypress-file-upload", "node"]
|
||||
},
|
||||
}
|
|
@ -3,14 +3,5 @@
|
|||
"name": "@kbn/threat-intelligence-plugin",
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0",
|
||||
"scripts": {
|
||||
"cypress": "../../../node_modules/.bin/cypress",
|
||||
"cypress:open": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ../../plugins/threat_intelligence/cypress/cypress.config.ts --ftr-config-file ../../test/threat_intelligence_cypress/cli_config_parallel",
|
||||
"cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run:spec": "yarn cypress:run:reporter --browser chrome --spec ${SPEC_LIST:-'./cypress/e2e/**/*.cy.ts'}; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/cases/*.cy.ts' --ftr-config-file ../../test/security_solution_cypress/cli_config; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run:reporter": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../security_solution/scripts/start_cypress_parallel run --config-file ../../plugins/threat_intelligence/cypress/cypress.config.ts --ftr-config-file ../../test/threat_intelligence_cypress/cli_config_parallel --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json",
|
||||
"cypress:run:respops": "yarn cypress:run:reporter --browser chrome --spec ./cypress/e2e/detection_alerts/*.cy.ts,./cypress/e2e/detection_rules/*.cy.ts,./cypress/e2e/exceptions/*.cy.ts --ftr-config-file ../../x-pack/test/security_solution_cypress/cli_config; status=$?; yarn junit:merge && exit $status",
|
||||
"junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-threat-intelligence/cypress/results/mochawesome*.json > ../../../target/kibana-threat-intelligence/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-threat-intelligence/cypress/results/output.json --reportDir ../../../target/kibana-threat-intelligence/cypress/results && mkdir -p ../../../target/junit && cp ../../../target/kibana-threat-intelligence/cypress/results/*.xml ../../../target/junit/"
|
||||
}
|
||||
"scripts": {}
|
||||
}
|
||||
|
|
|
@ -371,7 +371,7 @@ describe('Missing mappings', { tags: ['@ess'] }, () => {
|
|||
});
|
||||
|
||||
it('should display data grid despite the missing mappings and missing fields', () => {
|
||||
// there are 2 documents in the x-pack/test/threat_intelligence_cypress/es_archives/threat_intelligence/missing_mappings_indicators_data/data.json
|
||||
// there are 2 documents in the x-pack/test/security_solution_cypress/es_archives/ti_indicators_data_no_mappings/data.json
|
||||
const documentsNumber = 2;
|
||||
cy.get(INDICATORS_TABLE_ROW_CELL).should('have.length.gte', documentsNumber);
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* 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 { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { FtrProviderContext } from './ftr_provider_context';
|
||||
|
||||
import { ThreatIntelligenceConfigurableCypressTestRunner } from './runner';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const securitySolutionCypressConfig = await readConfigFile(require.resolve('./config.ts'));
|
||||
return {
|
||||
...securitySolutionCypressConfig.getAll(),
|
||||
|
||||
testRunner: (context: FtrProviderContext) =>
|
||||
ThreatIntelligenceConfigurableCypressTestRunner(context),
|
||||
};
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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 { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { CA_CERT_PATH } from '@kbn/dev-utils';
|
||||
import { services } from './services';
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const kibanaCommonTestsConfig = await readConfigFile(
|
||||
require.resolve('@kbn/test-suites-src/common/config')
|
||||
);
|
||||
const xpackFunctionalTestsConfig = await readConfigFile(
|
||||
require.resolve('../functional/config.base.js')
|
||||
);
|
||||
|
||||
return {
|
||||
...kibanaCommonTestsConfig.getAll(),
|
||||
|
||||
services,
|
||||
|
||||
esTestCluster: {
|
||||
...xpackFunctionalTestsConfig.get('esTestCluster'),
|
||||
serverArgs: [
|
||||
...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs'),
|
||||
// define custom es server here
|
||||
// API Keys is enabled at the top level
|
||||
'xpack.security.enabled=true',
|
||||
],
|
||||
},
|
||||
|
||||
kbnTestServer: {
|
||||
...xpackFunctionalTestsConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs'),
|
||||
'--csp.strict=false',
|
||||
'--csp.warnLegacyBrowsers=false',
|
||||
// define custom kibana server args here
|
||||
`--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,
|
||||
'--xpack.ruleRegistry.write.enabled=true',
|
||||
'--xpack.ruleRegistry.write.cache.enabled=false',
|
||||
'--xpack.ruleRegistry.unsafe.indexUpgrade.enabled=true',
|
||||
// Without below line, default interval for rules is 1m
|
||||
// See https://github.com/elastic/kibana/pull/125396 for details
|
||||
'--xpack.alerting.rules.minimumScheduleInterval.value=1s',
|
||||
'--xpack.ruleRegistry.unsafe.legacyMultiTenancy.enabled=true',
|
||||
`--xpack.securitySolution.enableExperimental=${JSON.stringify([])}`,
|
||||
`--home.disableWelcomeScreen=true`,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* 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 { GenericFtrProviderContext } from '@kbn/test';
|
||||
|
||||
import { services } from './services';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, {}>;
|
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export interface Pipeline {
|
||||
name: string;
|
||||
processors: Array<Record<string, unknown>>;
|
||||
on_failure?: Array<Record<string, unknown>>;
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* 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 { Pipeline } from './pipeline';
|
||||
|
||||
export const tiAbusechMalware: Pipeline = {
|
||||
name: 'logs-ti_abusech.malware-1.3.1',
|
||||
processors: [
|
||||
{
|
||||
set: {
|
||||
field: 'ecs.version',
|
||||
value: '8.2.0',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.kind',
|
||||
value: 'enrichment',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.category',
|
||||
value: 'threat',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.type',
|
||||
value: 'indicator',
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'message',
|
||||
target_field: 'event.original',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
json: {
|
||||
field: 'event.original',
|
||||
target_field: 'abusech.malware',
|
||||
},
|
||||
},
|
||||
{
|
||||
fingerprint: {
|
||||
fields: ['abusech.malware.md5_hash', 'abusech.malware.sha256_hash'],
|
||||
target_field: '_id',
|
||||
},
|
||||
},
|
||||
{
|
||||
date: {
|
||||
field: 'abusech.malware.firstseen',
|
||||
target_field: 'threat.indicator.first_seen',
|
||||
formats: ['yyyy-MM-dd HH:mm:ss z', 'yyyy-MM-dd HH:mm:ss Z', 'yyyy-MM-dd HH:mm:ss'],
|
||||
if: 'ctx.abusech?.malware?.firstseen != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.type',
|
||||
value: 'file',
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.file_size',
|
||||
target_field: 'threat.indicator.file.size',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.file_type',
|
||||
target_field: 'threat.indicator.file.type',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: 'abusech.malware.urlhaus_download',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
convert: {
|
||||
field: 'threat.indicator.file.size',
|
||||
type: 'long',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
convert: {
|
||||
field: 'abusech.malware.virustotal.percent',
|
||||
type: 'float',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.md5_hash',
|
||||
target_field: 'threat.indicator.file.hash.md5',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.sha256_hash',
|
||||
target_field: 'threat.indicator.file.hash.sha256',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.imphash',
|
||||
target_field: 'threat.indicator.file.pe.imphash',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.ssdeep',
|
||||
target_field: 'threat.indicator.file.hash.ssdeep',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malware.tlsh',
|
||||
target_field: 'threat.indicator.file.hash.tlsh',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{{threat.indicator.file.hash.md5}}}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.md5 != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{{threat.indicator.file.hash.sha256}}}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.sha256 != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{{threat.indicator.file.hash.ssdeep}}}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.ssdeep != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{{threat.indicator.file.pe.imphash}}}',
|
||||
if: 'ctx?.threat?.indicator?.file?.pe?.imphash != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{{threat.indicator.file.hash.tlsh}}}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.tlsh != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.type',
|
||||
value: 'unknown',
|
||||
if: 'ctx?.threat?.indicator?.type == null',
|
||||
},
|
||||
},
|
||||
{
|
||||
script: {
|
||||
lang: 'painless',
|
||||
if: 'ctx?.abusech != null',
|
||||
source:
|
||||
'void handleMap(Map map) {\n for (def x : map.values()) {\n if (x instanceof Map) {\n handleMap(x);\n } else if (x instanceof List) {\n handleList(x);\n }\n }\nmap.values().removeIf(v -> v == null);\n}\nvoid handleList(List list) {\n for (def x : list) {\n if (x instanceof Map) {\n handleMap(x);\n } else if (x instanceof List) {\n handleList(x);\n }\n }\n}\nhandleMap(ctx);\n',
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: 'event.original',
|
||||
if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))",
|
||||
ignore_failure: true,
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: ['abusech.malware.firstseen', 'message'],
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
on_failure: [
|
||||
{
|
||||
set: {
|
||||
field: 'error.message',
|
||||
value: '{{ _ingest.on_failure_message }}',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -1,356 +0,0 @@
|
|||
/*
|
||||
* 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 { Pipeline } from './pipeline';
|
||||
|
||||
export const tiAbusechMalwareBazaar: Pipeline = {
|
||||
name: 'logs-ti_abusech.malwarebazaar-1.3.1',
|
||||
processors: [
|
||||
{
|
||||
set: {
|
||||
field: 'ecs.version',
|
||||
value: '8.2.0',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.kind',
|
||||
value: 'enrichment',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.category',
|
||||
value: 'threat',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.type',
|
||||
value: 'indicator',
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'message',
|
||||
target_field: 'event.original',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
json: {
|
||||
field: 'event.original',
|
||||
target_field: 'abusech.malwarebazaar',
|
||||
},
|
||||
},
|
||||
{
|
||||
fingerprint: {
|
||||
fields: ['abusech.malwarebazaar.md5_hash', 'abusech.malwarebazaar.sha256_hash'],
|
||||
target_field: '_id',
|
||||
},
|
||||
},
|
||||
{
|
||||
date: {
|
||||
field: 'abusech.malwarebazaar.first_seen',
|
||||
target_field: 'threat.indicator.first_seen',
|
||||
formats: ['yyyy-MM-dd HH:mm:ss z', 'yyyy-MM-dd HH:mm:ss Z', 'yyyy-MM-dd HH:mm:ss'],
|
||||
if: 'ctx.abusech?.malwarebazaar?.first_seen != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
date: {
|
||||
field: 'abusech.malwarebazaar.last_seen',
|
||||
target_field: 'threat.indicator.last_seen',
|
||||
formats: ['yyyy-MM-dd HH:mm:ss z', 'yyyy-MM-dd HH:mm:ss Z', 'yyyy-MM-dd HH:mm:ss'],
|
||||
if: 'ctx.abusech?.malwarebazaar?.last_seen != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.type',
|
||||
value: 'file',
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.file_name',
|
||||
target_field: 'threat.indicator.file.name',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.file_type_mime',
|
||||
target_field: 'threat.indicator.file.mime_type',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.reporter',
|
||||
target_field: 'threat.indicator.provider',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.origin_country',
|
||||
target_field: 'threat.indicator.geo.country_iso_code',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.signature',
|
||||
target_field: 'threat.software.alias',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
foreach: {
|
||||
field: 'abusech.malwarebazaar.code_sign',
|
||||
ignore_missing: true,
|
||||
processor: {
|
||||
rename: {
|
||||
field: '_ingest._value.subject_cn',
|
||||
target_field: 'threat.indicator.file.x509.subject.common_name',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
foreach: {
|
||||
field: 'abusech.malwarebazaar.code_sign',
|
||||
ignore_missing: true,
|
||||
processor: {
|
||||
rename: {
|
||||
field: '_ingest._value.issuer_cn',
|
||||
target_field: 'threat.indicator.file.x509.issuer.common_name',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
foreach: {
|
||||
field: 'abusech.malwarebazaar.code_sign',
|
||||
ignore_missing: true,
|
||||
processor: {
|
||||
rename: {
|
||||
field: '_ingest._value.algorithm',
|
||||
target_field: 'threat.indicator.file.x509.public_key_algorithm',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
foreach: {
|
||||
field: 'abusech.malwarebazaar.code_sign',
|
||||
ignore_missing: true,
|
||||
processor: {
|
||||
rename: {
|
||||
field: '_ingest._value.valid_from',
|
||||
target_field: 'threat.indicator.file.x509.not_before',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
foreach: {
|
||||
field: 'abusech.malwarebazaar.code_sign',
|
||||
ignore_missing: true,
|
||||
processor: {
|
||||
rename: {
|
||||
field: '_ingest._value.valid_to',
|
||||
target_field: 'threat.indicator.file.x509.not_after',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
foreach: {
|
||||
field: 'abusech.malwarebazaar.code_sign',
|
||||
ignore_missing: true,
|
||||
processor: {
|
||||
rename: {
|
||||
field: '_ingest._value.serial_number',
|
||||
target_field: 'threat.indicator.file.x509.serial_number',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.file_size',
|
||||
target_field: 'threat.indicator.file.size',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.file_type',
|
||||
target_field: 'threat.indicator.file.extension',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.md5_hash',
|
||||
target_field: 'threat.indicator.file.hash.md5',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.sha256_hash',
|
||||
target_field: 'threat.indicator.file.hash.sha256',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.sha1_hash',
|
||||
target_field: 'threat.indicator.file.hash.sha1',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.sha3_384_hash',
|
||||
target_field: 'threat.indicator.file.hash.sha384',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.imphash',
|
||||
target_field: 'threat.indicator.file.pe.imphash',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.ssdeep',
|
||||
target_field: 'threat.indicator.file.hash.ssdeep',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.tlsh',
|
||||
target_field: 'threat.indicator.file.hash.tlsh',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.malwarebazaar.telfhash',
|
||||
target_field: 'threat.indicator.file.elf.telfhash',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{ threat.indicator.file.hash.md5 }}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.md5 != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{ threat.indicator.file.hash.sha256 }}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.sha256 != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{ threat.indicator.file.hash.ssdeep }}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.ssdeep != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{ threat.indicator.file.pe.imphash }}',
|
||||
if: 'ctx?.threat?.indicator?.file?.pe?.imphash != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{ threat.indicator.file.elf.telfhash }}',
|
||||
if: 'ctx?.threat?.indicator?.file?.elf?.telfhash != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
append: {
|
||||
field: 'related.hash',
|
||||
value: '{{ threat.indicator.file.hash.tlsh }}',
|
||||
if: 'ctx?.threat?.indicator?.file?.hash?.tlsh != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
convert: {
|
||||
field: 'threat.indicator.file.size',
|
||||
type: 'long',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
convert: {
|
||||
field: 'abusech.malwarebazaar.intelligence.downloads',
|
||||
type: 'long',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
convert: {
|
||||
field: 'abusech.malwarebazaar.intelligence.uploads',
|
||||
type: 'long',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.type',
|
||||
value: 'unknown',
|
||||
if: 'ctx?.threat?.indicator?.type == null',
|
||||
},
|
||||
},
|
||||
{
|
||||
script: {
|
||||
lang: 'painless',
|
||||
if: 'ctx?.abusech != null',
|
||||
source:
|
||||
'void handleMap(Map map) {\n for (def x : map.values()) {\n if (x instanceof Map) {\n handleMap(x);\n } else if (x instanceof List) {\n handleList(x);\n }\n }\nmap.values().removeIf(v -> v == null);\n}\nvoid handleList(List list) {\n for (def x : list) {\n if (x instanceof Map) {\n handleMap(x);\n } else if (x instanceof List) {\n handleList(x);\n }\n }\n}\nhandleMap(ctx);\n',
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: 'event.original',
|
||||
if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))",
|
||||
ignore_failure: true,
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: ['abusech.malwarebazaar.first_seen', 'abusech.malwarebazaar.last_seen', 'message'],
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
on_failure: [
|
||||
{
|
||||
set: {
|
||||
field: 'error.message',
|
||||
value: '{{ _ingest.on_failure_message }}',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* 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 { Pipeline } from './pipeline';
|
||||
|
||||
export const tiAbusechUrl: Pipeline = {
|
||||
name: 'logs-ti_abusech.url-1.3.1',
|
||||
processors: [
|
||||
{
|
||||
set: {
|
||||
field: 'ecs.version',
|
||||
value: '8.0.0',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.kind',
|
||||
value: 'enrichment',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.category',
|
||||
value: 'threat',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'event.type',
|
||||
value: 'indicator',
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'message',
|
||||
target_field: 'event.original',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
json: {
|
||||
field: 'event.original',
|
||||
target_field: 'abusech.url',
|
||||
},
|
||||
},
|
||||
{
|
||||
fingerprint: {
|
||||
fields: ['abusech.url.id'],
|
||||
target_field: '_id',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.type',
|
||||
value: 'url',
|
||||
},
|
||||
},
|
||||
{
|
||||
date: {
|
||||
field: 'abusech.url.date_added',
|
||||
target_field: 'threat.indicator.first_seen',
|
||||
formats: ['yyyy-MM-dd HH:mm:ss z', 'yyyy-MM-dd HH:mm:ss Z'],
|
||||
if: 'ctx.abusech?.url?.date_added != null',
|
||||
},
|
||||
},
|
||||
{
|
||||
uri_parts: {
|
||||
field: 'abusech.url.url',
|
||||
target_field: 'threat.indicator.url',
|
||||
keep_original: true,
|
||||
remove_if_successful: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.url.full',
|
||||
value: '{{{threat.indicator.url.original}}}',
|
||||
ignore_empty_value: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.url.urlhaus_reference',
|
||||
target_field: 'threat.indicator.reference',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
grok: {
|
||||
field: 'abusech.url.host',
|
||||
patterns: ['(?:%{IP:threat.indicator.ip}|%{GREEDYDATA:threat.indicator.url.domain})'],
|
||||
ignore_failure: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
rename: {
|
||||
field: 'abusech.url.reporter',
|
||||
target_field: 'threat.indicator.provider',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'threat.indicator.type',
|
||||
value: 'unknown',
|
||||
if: 'ctx?.threat?.indicator?.type == null',
|
||||
},
|
||||
},
|
||||
{
|
||||
convert: {
|
||||
field: 'abusech.url.larted',
|
||||
type: 'boolean',
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
script: {
|
||||
lang: 'painless',
|
||||
if: 'ctx?.abusech != null',
|
||||
source:
|
||||
'void handleMap(Map map) {\n for (def x : map.values()) {\n if (x instanceof Map) {\n handleMap(x);\n } else if (x instanceof List) {\n handleList(x);\n }\n }\nmap.values().removeIf(v -> v == null);\n}\nvoid handleList(List list) {\n for (def x : list) {\n if (x instanceof Map) {\n handleMap(x);\n } else if (x instanceof List) {\n handleList(x);\n }\n }\n}\nhandleMap(ctx);\n',
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: 'event.original',
|
||||
if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))",
|
||||
ignore_failure: true,
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
remove: {
|
||||
field: ['abusech.url.date_added', 'abusech.url.url', 'abusech.url.host', 'message'],
|
||||
ignore_missing: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
on_failure: [
|
||||
{
|
||||
set: {
|
||||
field: 'error.message',
|
||||
value: '{{ _ingest.on_failure_message }}',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* 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 { resolve } from 'path';
|
||||
|
||||
import Url from 'url';
|
||||
|
||||
import { withProcRunner } from '@kbn/dev-proc-runner';
|
||||
|
||||
import semver from 'semver';
|
||||
import { TransportResult } from '@elastic/elasticsearch';
|
||||
import { FtrProviderContext } from './ftr_provider_context';
|
||||
|
||||
import { tiAbusechMalware } from './pipelines/ti_abusech_malware';
|
||||
import { tiAbusechMalwareBazaar } from './pipelines/ti_abusech_malware_bazaar';
|
||||
import { tiAbusechUrl } from './pipelines/ti_abusech_url';
|
||||
|
||||
export async function ThreatIntelligenceConfigurableCypressTestRunner(
|
||||
{ getService }: FtrProviderContext,
|
||||
envVars?: Record<string, string>
|
||||
) {
|
||||
const log = getService('log');
|
||||
const config = getService('config');
|
||||
const es = getService('es');
|
||||
|
||||
const pipelines = [tiAbusechMalware, tiAbusechMalwareBazaar, tiAbusechUrl];
|
||||
|
||||
log.info('configure pipelines');
|
||||
|
||||
for (const pipeline of pipelines) {
|
||||
const res: TransportResult<unknown, any> = await es.transport.request({
|
||||
method: 'PUT',
|
||||
path: `_ingest/pipeline/${pipeline.name}`,
|
||||
body: {
|
||||
processors: pipeline.processors,
|
||||
on_failure: pipeline.on_failure,
|
||||
},
|
||||
});
|
||||
|
||||
log.info(`PUT pipeline ${pipeline.name}: ${res.statusCode}`);
|
||||
}
|
||||
|
||||
return {
|
||||
FORCE_COLOR: '1',
|
||||
CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')),
|
||||
CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')),
|
||||
CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'),
|
||||
CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
|
||||
...envVars,
|
||||
baseUrl: Url.format(config.get('servers.kibana')),
|
||||
BASE_URL: Url.format(config.get('servers.kibana')),
|
||||
ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')),
|
||||
ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'),
|
||||
ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
|
||||
};
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCcsTestRunner({ getService }: FtrProviderContext) {
|
||||
const log = getService('log');
|
||||
|
||||
await withProcRunner(log, async (procs) => {
|
||||
await procs.run('cypress', {
|
||||
cmd: 'yarn',
|
||||
args: ['cypress:run:ccs'],
|
||||
cwd: resolve(__dirname, '../../plugins/threat_intelligence'),
|
||||
env: {
|
||||
FORCE_COLOR: '1',
|
||||
CYPRESS_BASE_URL: process.env.TEST_KIBANA_URL,
|
||||
CYPRESS_ELASTICSEARCH_URL: process.env.TEST_ES_URL,
|
||||
CYPRESS_ELASTICSEARCH_USERNAME: process.env.ELASTICSEARCH_USERNAME,
|
||||
CYPRESS_ELASTICSEARCH_PASSWORD: process.env.ELASTICSEARCH_PASSWORD,
|
||||
CYPRESS_CCS_KIBANA_URL: process.env.TEST_KIBANA_URLDATA,
|
||||
CYPRESS_CCS_ELASTICSEARCH_URL: process.env.TEST_ES_URLDATA,
|
||||
CYPRESS_CCS_REMOTE_NAME: process.env.TEST_CCS_REMOTE_NAME,
|
||||
...process.env,
|
||||
},
|
||||
wait: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressUpgradeCliTestRunner({
|
||||
getService,
|
||||
}: FtrProviderContext) {
|
||||
const log = getService('log');
|
||||
let command = '';
|
||||
|
||||
if (semver.gt(process.env.ORIGINAL_VERSION!, '7.10.0')) {
|
||||
command = 'cypress:run:upgrade';
|
||||
} else {
|
||||
command = 'cypress:run:upgrade:old';
|
||||
}
|
||||
|
||||
await withProcRunner(log, async (procs) => {
|
||||
await procs.run('cypress', {
|
||||
cmd: 'yarn',
|
||||
args: [command],
|
||||
cwd: resolve(__dirname, '../../plugins/threat_intelligence'),
|
||||
env: {
|
||||
FORCE_COLOR: '1',
|
||||
CYPRESS_BASE_URL: process.env.TEST_KIBANA_URL,
|
||||
CYPRESS_ELASTICSEARCH_URL: process.env.TEST_ES_URL,
|
||||
CYPRESS_ELASTICSEARCH_USERNAME: process.env.TEST_ES_USER,
|
||||
CYPRESS_ELASTICSEARCH_PASSWORD: process.env.TEST_ES_PASS,
|
||||
CYPRESS_ORIGINAL_VERSION: process.env.ORIGINAL_VERSION,
|
||||
...process.env,
|
||||
},
|
||||
wait: true,
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from '@kbn/test-suites-src/common/services';
|
Loading…
Add table
Add a link
Reference in a new issue