mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Backport This will backport the following commits from `main` to `8.10`: - [Fix osquery cypress tests (#163988)](https://github.com/elastic/kibana/pull/163988) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Patryk Kopyciński","email":"contact@patrykkopycinski.com"},"sourceCommit":{"committedDate":"2023-08-16T22:11:05Z","message":"Fix osquery cypress tests (#163988)\n\n## Summary\r\n\r\nAdjust tests to https://github.com/elastic/kibana/pull/161614\r\nSplit tests into smaller files to better utilize parallelization and\r\nincrease the stability of tests","sha":"fd33ed55fd9bc81d006ca41c85b7bd4117741e80","branchLabelMapping":{"^v8.10.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:prev-minor","v8.10.0","v8.11.0"],"number":163988,"url":"https://github.com/elastic/kibana/pull/163988","mergeCommit":{"message":"Fix osquery cypress tests (#163988)\n\n## Summary\r\n\r\nAdjust tests to https://github.com/elastic/kibana/pull/161614\r\nSplit tests into smaller files to better utilize parallelization and\r\nincrease the stability of tests","sha":"fd33ed55fd9bc81d006ca41c85b7bd4117741e80"}},"sourceBranch":"main","suggestedTargetBranches":["8.11"],"targetPullRequestStates":[{"branch":"main","label":"v8.10.0","labelRegex":"^v8.10.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/163988","number":163988,"mergeCommit":{"message":"Fix osquery cypress tests (#163988)\n\n## Summary\r\n\r\nAdjust tests to https://github.com/elastic/kibana/pull/161614\r\nSplit tests into smaller files to better utilize parallelization and\r\nincrease the stability of tests","sha":"fd33ed55fd9bc81d006ca41c85b7bd4117741e80"}},{"branch":"8.11","label":"v8.11.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>
This commit is contained in:
parent
2b5b603171
commit
f8121b897d
20 changed files with 1628 additions and 1662 deletions
|
@ -12,3 +12,13 @@ steps:
|
|||
limit: 1
|
||||
artifact_paths:
|
||||
- "target/kibana-osquery/**/*"
|
||||
|
||||
- command: .buildkite/scripts/steps/functional/osquery_cypress_burn.sh
|
||||
label: 'Osquery Cypress Tests, burning changed specs'
|
||||
agents:
|
||||
queue: n2-4-spot
|
||||
depends_on: build
|
||||
timeout_in_minutes: 50
|
||||
soft_fail: true
|
||||
artifact_paths:
|
||||
- "target/kibana-osquery/**/*"
|
||||
|
|
|
@ -80,6 +80,7 @@ const uploadPipeline = (pipelineContent: string | object) => {
|
|||
getPipeline('.buildkite/pipelines/pull_request/security_solution_explore.yml')
|
||||
);
|
||||
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/defend_workflows.yml'));
|
||||
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/osquery_cypress.yml'));
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -200,7 +201,8 @@ const uploadPipeline = (pipelineContent: string | object) => {
|
|||
|
||||
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/post_build.yml'));
|
||||
|
||||
uploadPipeline(pipeline.join('\n'));
|
||||
// remove duplicated steps
|
||||
uploadPipeline([...new Set(pipeline)].join('\n'));
|
||||
} catch (ex) {
|
||||
console.error('PR pipeline generation error', ex.message);
|
||||
process.exit(1);
|
||||
|
|
17
.buildkite/scripts/steps/functional/osquery_cypress_burn.sh
Executable file
17
.buildkite/scripts/steps/functional/osquery_cypress_burn.sh
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source .buildkite/scripts/common/util.sh
|
||||
source .buildkite/scripts/steps/functional/common_cypress.sh
|
||||
|
||||
.buildkite/scripts/bootstrap.sh
|
||||
node scripts/build_kibana_platform_plugins.js
|
||||
|
||||
export JOB=kibana-osquery-cypress
|
||||
|
||||
buildkite-agent meta-data set "${BUILDKITE_JOB_ID}_is_test_execution_step" 'false'
|
||||
|
||||
echo "--- Osquery Cypress tests, burning changed specs (Chrome)"
|
||||
|
||||
yarn --cwd x-pack/plugins/osquery cypress:changed-specs-only
|
|
@ -36,6 +36,6 @@ export default defineCypressConfig({
|
|||
baseUrl: 'http://localhost:5601',
|
||||
experimentalRunAllSpecs: true,
|
||||
experimentalMemoryManagement: true,
|
||||
numTestsKeptInMemory: 10,
|
||||
numTestsKeptInMemory: 3,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,721 +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 {
|
||||
cleanupCase,
|
||||
cleanupPack,
|
||||
cleanupRule,
|
||||
loadCase,
|
||||
loadPack,
|
||||
loadRule,
|
||||
multiQueryPackFixture,
|
||||
packFixture,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import {
|
||||
RESPONSE_ACTIONS_ITEM_0,
|
||||
RESPONSE_ACTIONS_ITEM_1,
|
||||
RESPONSE_ACTIONS_ITEM_2,
|
||||
OSQUERY_RESPONSE_ACTION_ADD_BUTTON,
|
||||
} from '../../tasks/response_actions';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
addToCase,
|
||||
checkActionItemsInResults,
|
||||
findAndClickButton,
|
||||
findFormFieldByRowsLabelAndType,
|
||||
inputQuery,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
takeOsqueryActionWithParams,
|
||||
toggleRuleOffAndOn,
|
||||
typeInECSFieldInput,
|
||||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { preparePack } from '../../tasks/packs';
|
||||
import {
|
||||
closeDateTabIfVisible,
|
||||
closeModalIfVisible,
|
||||
closeToastIfVisible,
|
||||
generateRandomStringName,
|
||||
interceptCaseId,
|
||||
} from '../../tasks/integrations';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { RESULTS_TABLE, RESULTS_TABLE_BUTTON } from '../../screens/live_query';
|
||||
import { OSQUERY_POLICY } from '../../screens/fleet';
|
||||
|
||||
const UUID_REGEX = '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}';
|
||||
|
||||
describe('Alert Event Details', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
});
|
||||
|
||||
describe('Packs and rules creation', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
const packData = packFixture();
|
||||
|
||||
before(() => {
|
||||
loadPack(packData).then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should prepare packs and alert rules', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
cy.contains(`Edit ${packName}`);
|
||||
findFormFieldByRowsLabelAndType(
|
||||
'Scheduled agent policies (optional)',
|
||||
`${OSQUERY_POLICY}{downArrow}{enter}`
|
||||
);
|
||||
findAndClickButton('Update pack');
|
||||
closeModalIfVisible();
|
||||
cy.contains(`Successfully updated "${packName}" pack`);
|
||||
closeToastIfVisible();
|
||||
|
||||
toggleRuleOffAndOn(ruleName);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('Response actions', () => {
|
||||
let multiQueryPackId: string;
|
||||
let multiQueryPackName: string;
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
const packData = packFixture();
|
||||
const multiQueryPackData = multiQueryPackFixture();
|
||||
|
||||
beforeEach(() => {
|
||||
loadPack(packData).then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadPack(multiQueryPackData).then((data) => {
|
||||
multiQueryPackId = data.saved_object_id;
|
||||
multiQueryPackName = data.name;
|
||||
});
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupPack(multiQueryPackId);
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('adds response actions with osquery with proper validation and form values', () => {
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
closeDateTabIfVisible();
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
cy.contains('Response actions are run on each rule execution.');
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('Query is a required field');
|
||||
inputQuery('select * from uptime1');
|
||||
});
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('Run a set of queries in a pack').click();
|
||||
});
|
||||
cy.contains('Save changes').click();
|
||||
cy.getBySel('response-actions-error')
|
||||
.within(() => {
|
||||
cy.contains('Pack is a required field');
|
||||
})
|
||||
.should('exist');
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('Pack is a required field');
|
||||
cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => {
|
||||
cy.contains('Query is a required field');
|
||||
inputQuery('select * from uptime');
|
||||
cy.contains('Advanced').click();
|
||||
typeInECSFieldInput('message{downArrow}{enter}');
|
||||
cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}');
|
||||
cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
});
|
||||
|
||||
cy.getBySel('ruleEditSubmitButton').click();
|
||||
cy.contains(`${ruleName} was saved`).should('exist');
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('select * from uptime1');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => {
|
||||
cy.contains('select * from uptime');
|
||||
cy.contains('Log message optimized for viewing in a log viewer');
|
||||
cy.contains('Days of uptime');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains(packName);
|
||||
cy.getBySel('comboBoxInput').type('{backspace}{enter}');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('select * from uptime1');
|
||||
cy.getBySel('remove-response-action').click();
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('Search for a pack to run');
|
||||
cy.contains('Pack is a required field');
|
||||
cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('select * from uptime');
|
||||
cy.contains('Log message optimized for viewing in a log viewer');
|
||||
cy.contains('Days of uptime');
|
||||
});
|
||||
cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleSingleQuery');
|
||||
cy.getBySel('ruleEditSubmitButton').click();
|
||||
cy.wait('@saveRuleSingleQuery').should(({ request }) => {
|
||||
const oneQuery = [
|
||||
{
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
id: Object.keys(packData.queries)[0],
|
||||
},
|
||||
];
|
||||
expect(request.body.response_actions[0].params.queries).to.deep.equal(oneQuery);
|
||||
});
|
||||
|
||||
cy.contains(`${ruleName} was saved`).should('exist');
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains(packName);
|
||||
cy.getBySel('comboBoxInput').type(`${multiQueryPackName}{downArrow}{enter}`);
|
||||
checkActionItemsInResults({
|
||||
cases: false,
|
||||
lens: false,
|
||||
discover: false,
|
||||
timeline: false,
|
||||
});
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('select * from uptime');
|
||||
cy.contains('Log message optimized for viewing in a log viewer');
|
||||
cy.contains('Days of uptime');
|
||||
});
|
||||
cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleMultiQuery');
|
||||
|
||||
cy.contains('Save changes').click();
|
||||
cy.wait('@saveRuleMultiQuery').should(({ request }) => {
|
||||
const threeQueries = [
|
||||
{
|
||||
interval: 3600,
|
||||
query: 'SELECT * FROM memory_info;',
|
||||
platform: 'linux',
|
||||
id: Object.keys(multiQueryPackData.queries)[0],
|
||||
},
|
||||
{
|
||||
interval: 3600,
|
||||
query: 'SELECT * FROM system_info;',
|
||||
id: Object.keys(multiQueryPackData.queries)[1],
|
||||
},
|
||||
{
|
||||
interval: 10,
|
||||
query: 'select opera_extensions.* from users join opera_extensions using (uid);',
|
||||
id: Object.keys(multiQueryPackData.queries)[2],
|
||||
},
|
||||
];
|
||||
expect(request.body.response_actions[0].params.queries).to.deep.equal(threeQueries);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('investigation guide', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should be able to add investigation guides to response actions', () => {
|
||||
const investigationGuideNote =
|
||||
'You have queries in the investigation guide. Add them as response actions?';
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
|
||||
cy.contains(investigationGuideNote);
|
||||
cy.getBySel('osqueryAddInvestigationGuideQueries').click();
|
||||
cy.contains(investigationGuideNote).should('not.exist');
|
||||
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains("SELECT * FROM os_version where name='{{host.os.name}}';");
|
||||
cy.contains('host.os.platform');
|
||||
cy.contains('platform');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('select * from users');
|
||||
});
|
||||
cy.contains('Save changes').click();
|
||||
cy.contains(`${ruleName} was saved`).should('exist');
|
||||
closeToastIfVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('timeline', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
it('should be able to run live query and add to timeline (-depending on the previous test)', () => {
|
||||
const TIMELINE_NAME = 'Untitled timeline';
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('timeline-context-menu-button').first().click();
|
||||
cy.contains('Run Osquery');
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
cy.contains('1 agent selected.');
|
||||
inputQuery('select * from uptime;');
|
||||
submitQuery();
|
||||
cy.contains('Results');
|
||||
cy.contains('Add to timeline investigation');
|
||||
cy.contains('Save for later').click();
|
||||
cy.contains('Save query');
|
||||
cy.get('[data-test-subj="osquery-save-query-flyout"]').within(() => {
|
||||
cy.get('.euiButtonEmpty').contains('Cancel').click();
|
||||
});
|
||||
cy.getBySel('add-to-timeline').first().click();
|
||||
cy.getBySel('globalToastList').contains('Added');
|
||||
closeToastIfVisible();
|
||||
cy.getBySel(RESULTS_TABLE).within(() => {
|
||||
cy.getBySel(RESULTS_TABLE_BUTTON).should('not.exist');
|
||||
});
|
||||
cy.contains('Cancel').click();
|
||||
cy.getBySel('flyoutBottomBar').within(() => {
|
||||
cy.contains(TIMELINE_NAME).click();
|
||||
});
|
||||
cy.getBySel('draggableWrapperKeyboardHandler').contains('action_id: "');
|
||||
// timeline unsaved changes modal
|
||||
cy.visit('/app/osquery');
|
||||
closeModalIfVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('substitute params', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should substitute parameters in investigation guide', () => {
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.contains('Get processes').click();
|
||||
cy.getBySel('flyout-body-osquery').within(() => {
|
||||
cy.contains("SELECT * FROM os_version where name='Ubuntu';");
|
||||
cy.contains('host.os.platform');
|
||||
cy.contains('platform');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('Case creation', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
let caseId: string;
|
||||
const packData = packFixture();
|
||||
|
||||
before(() => {
|
||||
loadPack(packData).then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
interceptCaseId((id) => {
|
||||
caseId = id;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupRule(ruleId);
|
||||
cleanupCase(caseId);
|
||||
});
|
||||
|
||||
it('runs osquery against alert and creates a new case', () => {
|
||||
const [caseName, caseDescription] = generateRandomStringName(2);
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click({ force: true });
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
cy.contains('Run a set of queries in a pack').wait(500).click();
|
||||
cy.getBySel('select-live-pack').within(() => {
|
||||
cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
submitQuery();
|
||||
cy.get('[aria-label="Add to Case"]').first().click();
|
||||
cy.getBySel('cases-table-add-case-filter-bar').click();
|
||||
cy.getBySel('create-case-flyout').should('be.visible');
|
||||
cy.getBySel('caseTitle').within(() => {
|
||||
cy.getBySel('input').type(caseName);
|
||||
});
|
||||
cy.getBySel('caseDescription').within(() => {
|
||||
cy.getBySel('euiMarkdownEditorTextArea').type(caseDescription);
|
||||
});
|
||||
cy.getBySel('create-case-submit').click();
|
||||
cy.contains(`An alert was added to "${caseName}"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Case', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
loadCase('securitySolution').then((data) => {
|
||||
caseId = data.id;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
cleanupCase(caseId);
|
||||
});
|
||||
|
||||
it('sees osquery results from last action and add to a case', () => {
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('responseActionsViewTab').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
cy.contains('select * from users;');
|
||||
cy.contains("SELECT * FROM os_version where name='Ubuntu';");
|
||||
cy.getBySel('osquery-results-comment').each(($comment) => {
|
||||
cy.wrap($comment).within(() => {
|
||||
// On initial load result table might not render due to displayed error
|
||||
if ($comment.find('div .euiDataGridRow').length <= 0) {
|
||||
// If tabs are present try clicking between status and results to get rid of the error message
|
||||
if ($comment.find('div .euiTabs').length > 0) {
|
||||
cy.getBySel('osquery-status-tab').click();
|
||||
cy.getBySel('osquery-results-tab').click();
|
||||
cy.getBySel('dataGridRowCell', { timeout: 120000 }).should('have.lengthOf.above', 0);
|
||||
}
|
||||
} else {
|
||||
// Result tab was rendered successfully
|
||||
cy.getBySel('dataGridRowCell', { timeout: 120000 }).should('have.lengthOf.above', 0);
|
||||
}
|
||||
// }
|
||||
});
|
||||
});
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
addToCase(caseId);
|
||||
viewRecentCaseAndCheckResults();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Discover', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('can visit discover from response action results', () => {
|
||||
const discoverRegex = new RegExp(`action_id: ${UUID_REGEX}`);
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('responseActionsViewTab').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
cy.contains('View in Discover')
|
||||
.should('exist')
|
||||
.should('have.attr', 'href')
|
||||
.then(($href) => {
|
||||
// @ts-expect-error-next-line href string - check types
|
||||
cy.visit($href);
|
||||
cy.getBySel('breadcrumbs').contains('Discover').should('exist');
|
||||
cy.getBySel('discoverDocTable', { timeout: 60000 }).within(() => {
|
||||
cy.contains(`action_data.query`);
|
||||
});
|
||||
cy.contains(discoverRegex);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Lens', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('can visit lens from response action results', () => {
|
||||
const lensRegex = new RegExp(`Action ${UUID_REGEX} results`);
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('responseActionsViewTab').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
cy.getBySel('osquery-results-comment')
|
||||
.first()
|
||||
.within(() => {
|
||||
let lensUrl = '';
|
||||
cy.window().then((win) => {
|
||||
cy.stub(win, 'open')
|
||||
.as('windowOpen')
|
||||
.callsFake((url) => {
|
||||
lensUrl = url;
|
||||
});
|
||||
});
|
||||
cy.get(`[aria-label="View in Lens"]`).click();
|
||||
cy.window()
|
||||
.its('open')
|
||||
.then(() => {
|
||||
cy.visit(lensUrl);
|
||||
});
|
||||
});
|
||||
cy.getBySel('lnsWorkspace').should('exist');
|
||||
cy.getBySel('breadcrumbs').contains(lensRegex);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Timeline', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('can add to timeline from response action results', () => {
|
||||
const timelineRegex = new RegExp(`Added ${UUID_REGEX} to timeline`);
|
||||
const filterRegex = new RegExp(`action_id: "${UUID_REGEX}"`);
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('responseActionsViewTab').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
cy.getBySel('osquery-results-comment')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('.euiTableRow')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.getBySel('add-to-timeline').click();
|
||||
});
|
||||
});
|
||||
cy.contains(timelineRegex);
|
||||
cy.getBySel('flyoutBottomBar').contains('Untitled timeline').click();
|
||||
cy.contains(filterRegex);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Params', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should substitute parameters in live query and increase number of ran queries', () => {
|
||||
let initialNotificationCount: number;
|
||||
let updatedNotificationCount: number;
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('response-actions-notification')
|
||||
.should('not.have.text', '0')
|
||||
.then((element) => {
|
||||
initialNotificationCount = parseInt(element.text(), 10);
|
||||
});
|
||||
takeOsqueryActionWithParams();
|
||||
cy.getBySel('osquery-empty-button').click();
|
||||
cy.getBySel('response-actions-notification')
|
||||
.should('not.have.text', '0')
|
||||
.then((element) => {
|
||||
updatedNotificationCount = parseInt(element.text(), 10);
|
||||
expect(initialNotificationCount).to.be.equal(updatedNotificationCount - 1);
|
||||
})
|
||||
.then(() => {
|
||||
cy.getBySel('responseActionsViewTab').click();
|
||||
cy.getBySel('responseActionsViewWrapper').within(() => {
|
||||
cy.contains('tags');
|
||||
cy.getBySel('osquery-results-comment').should('have.length', updatedNotificationCount);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Multiple agents', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should be able to run take action query against all enrolled agents', () => {
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
cy.getBySel('agentSelection').within(() => {
|
||||
cy.getBySel('comboBoxClearButton').click();
|
||||
cy.getBySel('comboBoxInput').type('All{downArrow}{enter}{esc}');
|
||||
cy.contains('All agents');
|
||||
});
|
||||
inputQuery("SELECT * FROM os_version where name='{{host.os.name}}';", {
|
||||
parseSpecialCharSequences: false,
|
||||
});
|
||||
cy.wait(1000);
|
||||
submitQuery();
|
||||
cy.getBySel('flyout-body-osquery').within(() => {
|
||||
// at least 2 agents should have responded, sometimes it takes a while for the agents to respond
|
||||
cy.get('[data-grid-row-index]', { timeout: 6000000 }).should('have.length.at.least', 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Params in timeline', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should substitute params in osquery ran from timelines alerts', () => {
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('send-alert-to-timeline-button').first().click();
|
||||
cy.getBySel('query-events-table').within(() => {
|
||||
cy.getBySel('expand-event').first().click();
|
||||
});
|
||||
takeOsqueryActionWithParams();
|
||||
});
|
||||
});
|
||||
});
|
141
x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts
Normal file
141
x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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 {
|
||||
cleanupCase,
|
||||
cleanupPack,
|
||||
cleanupRule,
|
||||
loadCase,
|
||||
loadPack,
|
||||
loadRule,
|
||||
packFixture,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
addToCase,
|
||||
checkActionItemsInResults,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { generateRandomStringName, interceptCaseId } from '../../tasks/integrations';
|
||||
|
||||
describe('Alert Event Details - Cases', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
const packData = packFixture();
|
||||
|
||||
before(() => {
|
||||
loadPack(packData).then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
loadRuleAlerts(data.name);
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
describe('Case creation', () => {
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
interceptCaseId((id) => {
|
||||
caseId = id;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupCase(caseId);
|
||||
});
|
||||
|
||||
it('runs osquery against alert and creates a new case', () => {
|
||||
const [caseName, caseDescription] = generateRandomStringName(2);
|
||||
cy.getBySel('expand-event').first().click({ force: true });
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
cy.contains('Run a set of queries in a pack').wait(500).click();
|
||||
cy.getBySel('select-live-pack').within(() => {
|
||||
cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
submitQuery();
|
||||
cy.get('[aria-label="Add to Case"]').first().click();
|
||||
cy.getBySel('cases-table-add-case-filter-bar').click();
|
||||
cy.getBySel('create-case-flyout').should('be.visible');
|
||||
cy.getBySel('caseTitle').within(() => {
|
||||
cy.getBySel('input').type(caseName);
|
||||
});
|
||||
cy.getBySel('caseDescription').within(() => {
|
||||
cy.getBySel('euiMarkdownEditorTextArea').type(caseDescription);
|
||||
});
|
||||
cy.getBySel('create-case-submit').click();
|
||||
cy.contains(`An alert was added to "${caseName}"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Case', () => {
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
loadCase('securitySolution').then((data) => {
|
||||
caseId = data.id;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupCase(caseId);
|
||||
});
|
||||
|
||||
it('sees osquery results from last action and add to a case', () => {
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
cy.contains('select * from users;');
|
||||
cy.contains("SELECT * FROM os_version where name='Ubuntu';");
|
||||
cy.getBySel('osquery-results-comment').each(($comment) => {
|
||||
cy.wrap($comment).within(() => {
|
||||
// On initial load result table might not render due to displayed error
|
||||
if ($comment.find('div .euiDataGridRow').length <= 0) {
|
||||
// If tabs are present try clicking between status and results to get rid of the error message
|
||||
if ($comment.find('div .euiTabs').length > 0) {
|
||||
cy.getBySel('osquery-status-tab').click();
|
||||
cy.getBySel('osquery-results-tab').click();
|
||||
cy.getBySel('dataGridRowCell', { timeout: 120000 }).should('have.lengthOf.above', 0);
|
||||
}
|
||||
} else {
|
||||
// Result tab was rendered successfully
|
||||
cy.getBySel('dataGridRowCell', { timeout: 120000 }).should('have.lengthOf.above', 0);
|
||||
}
|
||||
// }
|
||||
});
|
||||
});
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
addToCase(caseId);
|
||||
viewRecentCaseAndCheckResults();
|
||||
});
|
||||
});
|
||||
});
|
188
x-pack/plugins/osquery/cypress/e2e/all/alerts_liked_apps.cy.ts
Normal file
188
x-pack/plugins/osquery/cypress/e2e/all/alerts_liked_apps.cy.ts
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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 { cleanupRule, loadRule } from '../../tasks/api_fixtures';
|
||||
import { RESPONSE_ACTIONS_ITEM_0, RESPONSE_ACTIONS_ITEM_1 } from '../../tasks/response_actions';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
inputQuery,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { closeModalIfVisible, closeToastIfVisible } from '../../tasks/integrations';
|
||||
import { RESULTS_TABLE, RESULTS_TABLE_BUTTON } from '../../screens/live_query';
|
||||
|
||||
const UUID_REGEX = '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}';
|
||||
|
||||
describe('Alert Event Details', { browser: 'electron' }, () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
loadRuleAlerts(data.name);
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
});
|
||||
|
||||
it('should be able to add investigation guides to response actions', () => {
|
||||
const investigationGuideNote =
|
||||
'You have queries in the investigation guide. Add them as response actions?';
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
|
||||
cy.contains(investigationGuideNote);
|
||||
cy.getBySel('osqueryAddInvestigationGuideQueries').click();
|
||||
cy.contains(investigationGuideNote).should('not.exist');
|
||||
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains("SELECT * FROM os_version where name='{{host.os.name}}';");
|
||||
cy.contains('host.os.platform');
|
||||
cy.contains('platform');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('select * from users');
|
||||
});
|
||||
cy.contains('Save changes').click();
|
||||
cy.contains(`${ruleName} was saved`).should('exist');
|
||||
closeToastIfVisible();
|
||||
});
|
||||
|
||||
it('should be able to run live query and add to timeline', () => {
|
||||
const TIMELINE_NAME = 'Untitled timeline';
|
||||
cy.getBySel('timeline-context-menu-button').first().click();
|
||||
cy.contains('Run Osquery');
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
cy.contains('1 agent selected.');
|
||||
inputQuery('select * from uptime;');
|
||||
submitQuery();
|
||||
cy.contains('Results');
|
||||
cy.contains('Add to timeline investigation');
|
||||
cy.contains('Save for later').click();
|
||||
cy.contains('Save query');
|
||||
cy.get('[data-test-subj="osquery-save-query-flyout"]').within(() => {
|
||||
cy.get('.euiButtonEmpty').contains('Cancel').click();
|
||||
});
|
||||
cy.getBySel('add-to-timeline').first().click();
|
||||
cy.getBySel('globalToastList').contains('Added');
|
||||
closeToastIfVisible();
|
||||
cy.getBySel(RESULTS_TABLE).within(() => {
|
||||
cy.getBySel(RESULTS_TABLE_BUTTON).should('not.exist');
|
||||
});
|
||||
cy.contains('Cancel').click();
|
||||
cy.getBySel('flyoutBottomBar').within(() => {
|
||||
cy.contains(TIMELINE_NAME).click();
|
||||
});
|
||||
cy.getBySel('draggableWrapperKeyboardHandler').contains('action_id: "');
|
||||
// timeline unsaved changes modal
|
||||
cy.visit('/app/osquery');
|
||||
closeModalIfVisible();
|
||||
});
|
||||
|
||||
it('can visit discover from response action results', () => {
|
||||
const discoverRegex = new RegExp(`action_id: ${UUID_REGEX}`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
cy.contains('View in Discover')
|
||||
.should('exist')
|
||||
.should('have.attr', 'href')
|
||||
.then(($href) => {
|
||||
// @ts-expect-error-next-line href string - check types
|
||||
cy.visit($href);
|
||||
cy.getBySel('breadcrumbs').contains('Discover').should('exist');
|
||||
cy.getBySel('discoverDocTable', { timeout: 60000 }).within(() => {
|
||||
cy.contains(`action_data.query`);
|
||||
});
|
||||
cy.contains(discoverRegex);
|
||||
});
|
||||
});
|
||||
|
||||
it('can visit lens from response action results', () => {
|
||||
const lensRegex = new RegExp(`Action ${UUID_REGEX} results`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
cy.getBySel('osquery-results-comment')
|
||||
.first()
|
||||
.within(() => {
|
||||
let lensUrl = '';
|
||||
cy.window().then((win) => {
|
||||
cy.stub(win, 'open')
|
||||
.as('windowOpen')
|
||||
.callsFake((url) => {
|
||||
lensUrl = url;
|
||||
});
|
||||
});
|
||||
cy.get(`[aria-label="View in Lens"]`).click();
|
||||
cy.window()
|
||||
.its('open')
|
||||
.then(() => {
|
||||
cy.visit(lensUrl);
|
||||
});
|
||||
});
|
||||
cy.getBySel('lnsWorkspace').should('exist');
|
||||
cy.getBySel('breadcrumbs').contains(lensRegex);
|
||||
});
|
||||
|
||||
it('can add to timeline from response action results', () => {
|
||||
const timelineRegex = new RegExp(`Added ${UUID_REGEX} to timeline`);
|
||||
const filterRegex = new RegExp(`action_id: "${UUID_REGEX}"`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.getBySel('responseActionsViewWrapper').should('exist');
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
cy.getBySel('osquery-results-comment')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('.euiTableRow')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.getBySel('add-to-timeline').click();
|
||||
});
|
||||
});
|
||||
cy.contains(timelineRegex);
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutHeaderCollapseDetailButton').click();
|
||||
cy.getBySel('flyoutBottomBar').contains('Untitled timeline').click();
|
||||
cy.contains(filterRegex);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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 { cleanupRule, loadRule } from '../../tasks/api_fixtures';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
inputQuery,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
takeOsqueryActionWithParams,
|
||||
} from '../../tasks/live_query';
|
||||
|
||||
describe('Alert Event Details - dynamic params', () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
loadRuleAlerts(data.name);
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
});
|
||||
|
||||
it('should substitute parameters in investigation guide', () => {
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutInvestigationGuideButton').click();
|
||||
cy.contains('Get processes').click();
|
||||
cy.getBySel('flyout-body-osquery').within(() => {
|
||||
cy.contains("SELECT * FROM os_version where name='Ubuntu';");
|
||||
cy.contains('host.os.platform');
|
||||
cy.contains('platform');
|
||||
});
|
||||
});
|
||||
|
||||
// response-actions-notification doesn't exist in expandable flyout
|
||||
it.skip('should substitute parameters in live query and increase number of ran queries', () => {
|
||||
let initialNotificationCount: number;
|
||||
let updatedNotificationCount: number;
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('response-actions-notification')
|
||||
.should('not.have.text', '0')
|
||||
.then((element) => {
|
||||
initialNotificationCount = parseInt(element.text(), 10);
|
||||
});
|
||||
takeOsqueryActionWithParams();
|
||||
cy.getBySel('osquery-empty-button').click();
|
||||
cy.getBySel('response-actions-notification')
|
||||
.should('not.have.text', '0')
|
||||
.then((element) => {
|
||||
updatedNotificationCount = parseInt(element.text(), 10);
|
||||
expect(initialNotificationCount).to.be.equal(updatedNotificationCount - 1);
|
||||
})
|
||||
.then(() => {
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.getBySel('responseActionsViewWrapper').within(() => {
|
||||
cy.contains('tags');
|
||||
cy.getBySel('osquery-results-comment').should('have.length', updatedNotificationCount);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to run take action query against all enrolled agents', () => {
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
cy.getBySel('agentSelection').within(() => {
|
||||
cy.getBySel('comboBoxClearButton').click();
|
||||
cy.getBySel('comboBoxInput').type('All{downArrow}{enter}{esc}');
|
||||
cy.contains('All agents');
|
||||
});
|
||||
inputQuery("SELECT * FROM os_version where name='{{host.os.name}}';", {
|
||||
parseSpecialCharSequences: false,
|
||||
});
|
||||
cy.wait(1000);
|
||||
submitQuery();
|
||||
cy.getBySel('flyout-body-osquery').within(() => {
|
||||
// at least 2 agents should have responded, sometimes it takes a while for the agents to respond
|
||||
cy.get('[data-grid-row-index]', { timeout: 6000000 }).should('have.length.at.least', 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should substitute params in osquery ran from timelines alerts', () => {
|
||||
loadRuleAlerts(ruleName);
|
||||
cy.getBySel('send-alert-to-timeline-button').first().click();
|
||||
cy.getBySel('query-events-table').within(() => {
|
||||
cy.getBySel('expand-event').first().click();
|
||||
});
|
||||
takeOsqueryActionWithParams();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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 {
|
||||
cleanupPack,
|
||||
cleanupRule,
|
||||
loadPack,
|
||||
loadRule,
|
||||
multiQueryPackFixture,
|
||||
packFixture,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import {
|
||||
RESPONSE_ACTIONS_ITEM_0,
|
||||
RESPONSE_ACTIONS_ITEM_1,
|
||||
RESPONSE_ACTIONS_ITEM_2,
|
||||
OSQUERY_RESPONSE_ACTION_ADD_BUTTON,
|
||||
} from '../../tasks/response_actions';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { checkActionItemsInResults, inputQuery, typeInECSFieldInput } from '../../tasks/live_query';
|
||||
import { closeDateTabIfVisible, closeToastIfVisible } from '../../tasks/integrations';
|
||||
|
||||
describe('Alert Event Details - Response Actions Form', { browser: 'electron' }, () => {
|
||||
let multiQueryPackId: string;
|
||||
let multiQueryPackName: string;
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
const packData = packFixture();
|
||||
const multiQueryPackData = multiQueryPackFixture();
|
||||
|
||||
beforeEach(() => {
|
||||
loadPack(packData).then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadPack(multiQueryPackData).then((data) => {
|
||||
multiQueryPackId = data.saved_object_id;
|
||||
multiQueryPackName = data.name;
|
||||
});
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
login(ROLE.soc_manager);
|
||||
});
|
||||
afterEach(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupPack(multiQueryPackId);
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('adds response actions with osquery with proper validation and form values', () => {
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
closeDateTabIfVisible();
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
cy.contains('Response actions are run on each rule execution.');
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('Query is a required field');
|
||||
inputQuery('select * from uptime1');
|
||||
});
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('Run a set of queries in a pack').click();
|
||||
});
|
||||
cy.contains('Save changes').click();
|
||||
cy.getBySel('response-actions-error')
|
||||
.within(() => {
|
||||
cy.contains('Pack is a required field');
|
||||
})
|
||||
.should('exist');
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('Pack is a required field');
|
||||
cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => {
|
||||
cy.contains('Query is a required field');
|
||||
inputQuery('select * from uptime');
|
||||
cy.contains('Advanced').click();
|
||||
typeInECSFieldInput('message{downArrow}{enter}');
|
||||
cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}');
|
||||
cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
});
|
||||
|
||||
cy.getBySel('ruleEditSubmitButton').click();
|
||||
cy.contains(`${ruleName} was saved`).should('exist');
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('select * from uptime1');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => {
|
||||
cy.contains('select * from uptime');
|
||||
cy.contains('Log message optimized for viewing in a log viewer');
|
||||
cy.contains('Days of uptime');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains(packName);
|
||||
cy.getBySel('comboBoxInput').type('{backspace}{enter}');
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('select * from uptime1');
|
||||
cy.getBySel('remove-response-action').click();
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains('Search for a pack to run');
|
||||
cy.contains('Pack is a required field');
|
||||
cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('select * from uptime');
|
||||
cy.contains('Log message optimized for viewing in a log viewer');
|
||||
cy.contains('Days of uptime');
|
||||
});
|
||||
cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleSingleQuery');
|
||||
cy.getBySel('ruleEditSubmitButton').click();
|
||||
cy.wait('@saveRuleSingleQuery').should(({ request }) => {
|
||||
const oneQuery = [
|
||||
{
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
id: Object.keys(packData.queries)[0],
|
||||
},
|
||||
];
|
||||
expect(request.body.response_actions[0].params.queries).to.deep.equal(oneQuery);
|
||||
});
|
||||
|
||||
cy.contains(`${ruleName} was saved`).should('exist');
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.getBySel('editRuleSettingsLink').click();
|
||||
cy.getBySel('globalLoadingIndicator').should('not.exist');
|
||||
cy.getBySel('edit-rule-actions-tab').click();
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => {
|
||||
cy.contains(packName);
|
||||
cy.getBySel('comboBoxInput').type(`${multiQueryPackName}{downArrow}{enter}`);
|
||||
checkActionItemsInResults({
|
||||
cases: false,
|
||||
lens: false,
|
||||
discover: false,
|
||||
timeline: false,
|
||||
});
|
||||
});
|
||||
cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => {
|
||||
cy.contains('select * from uptime');
|
||||
cy.contains('Log message optimized for viewing in a log viewer');
|
||||
cy.contains('Days of uptime');
|
||||
});
|
||||
cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleMultiQuery');
|
||||
|
||||
cy.contains('Save changes').click();
|
||||
cy.wait('@saveRuleMultiQuery').should(({ request }) => {
|
||||
const threeQueries = [
|
||||
{
|
||||
interval: 3600,
|
||||
query: 'SELECT * FROM memory_info;',
|
||||
platform: 'linux',
|
||||
id: Object.keys(multiQueryPackData.queries)[0],
|
||||
},
|
||||
{
|
||||
interval: 3600,
|
||||
query: 'SELECT * FROM system_info;',
|
||||
id: Object.keys(multiQueryPackData.queries)[1],
|
||||
},
|
||||
{
|
||||
interval: 10,
|
||||
query: 'select opera_extensions.* from users join opera_extensions using (uid);',
|
||||
id: Object.keys(multiQueryPackData.queries)[2],
|
||||
},
|
||||
];
|
||||
expect(request.body.response_actions[0].params.queries).to.deep.equal(threeQueries);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,934 +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 { find } from 'lodash';
|
||||
import type { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { API_VERSIONS } from '../../../common/constants';
|
||||
import { FLEET_AGENT_POLICIES, navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
deleteAndConfirm,
|
||||
findAndClickButton,
|
||||
findFormFieldByRowsLabelAndType,
|
||||
inputQuery,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
activatePack,
|
||||
cleanupAllPrebuiltPacks,
|
||||
deactivatePack,
|
||||
preparePack,
|
||||
} from '../../tasks/packs';
|
||||
import {
|
||||
addIntegration,
|
||||
closeModalIfVisible,
|
||||
closeToastIfVisible,
|
||||
generateRandomStringName,
|
||||
interceptPackId,
|
||||
interceptAgentPolicyId,
|
||||
} from '../../tasks/integrations';
|
||||
import { DEFAULT_POLICY, OSQUERY_POLICY } from '../../screens/fleet';
|
||||
import {
|
||||
getIdFormField,
|
||||
getSavedQueriesDropdown,
|
||||
LIVE_QUERY_EDITOR,
|
||||
} from '../../screens/live_query';
|
||||
import {
|
||||
loadSavedQuery,
|
||||
cleanupSavedQuery,
|
||||
cleanupPack,
|
||||
loadPack,
|
||||
cleanupAgentPolicy,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import { request } from '../../tasks/common';
|
||||
|
||||
describe('ALL - Packs', () => {
|
||||
let savedQueryId: string;
|
||||
let savedQueryName: string;
|
||||
let nomappingSavedQueryId: string;
|
||||
let nomappingSavedQueryName: string;
|
||||
let oneMappingSavedQueryId: string;
|
||||
let oneMappingSavedQueryName: string;
|
||||
let multipleMappingsSavedQueryId: string;
|
||||
let multipleMappingsSavedQueryName: string;
|
||||
|
||||
const integration = 'Osquery Manager';
|
||||
const PACK_NAME = 'Pack-name' + generateRandomStringName(1)[0];
|
||||
|
||||
describe('Create and edit a pack', () => {
|
||||
before(() => {
|
||||
loadSavedQuery().then((data) => {
|
||||
savedQueryId = data.saved_object_id;
|
||||
savedQueryName = data.id;
|
||||
});
|
||||
loadSavedQuery({
|
||||
ecs_mapping: {},
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
}).then((data) => {
|
||||
nomappingSavedQueryId = data.saved_object_id;
|
||||
nomappingSavedQueryName = data.id;
|
||||
});
|
||||
loadSavedQuery({
|
||||
ecs_mapping: {
|
||||
'client.geo.continent_name': {
|
||||
field: 'seconds',
|
||||
},
|
||||
},
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
}).then((data) => {
|
||||
oneMappingSavedQueryId = data.saved_object_id;
|
||||
oneMappingSavedQueryName = data.id;
|
||||
});
|
||||
loadSavedQuery({
|
||||
ecs_mapping: {
|
||||
labels: {
|
||||
field: 'days',
|
||||
},
|
||||
tags: {
|
||||
field: 'seconds',
|
||||
},
|
||||
'client.address': {
|
||||
field: 'total_seconds',
|
||||
},
|
||||
},
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
}).then((data) => {
|
||||
multipleMappingsSavedQueryId = data.saved_object_id;
|
||||
multipleMappingsSavedQueryName = data.id;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
cleanupSavedQuery(nomappingSavedQueryId);
|
||||
cleanupSavedQuery(oneMappingSavedQueryId);
|
||||
cleanupSavedQuery(multipleMappingsSavedQueryId);
|
||||
});
|
||||
|
||||
describe('Check if result type is correct', () => {
|
||||
let resultTypePackId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
resultTypePackId = pack;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(resultTypePackId);
|
||||
});
|
||||
|
||||
it('Check if result type is correct', () => {
|
||||
const packName = 'ResultType' + generateRandomStringName(1)[0];
|
||||
|
||||
cy.contains('Packs').click();
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', packName);
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getIdFormField().type('Query1');
|
||||
inputQuery('select * from uptime;');
|
||||
cy.wait(500); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getIdFormField().type('Query2');
|
||||
inputQuery('select * from uptime;');
|
||||
|
||||
cy.getBySel('resultsTypeField').click();
|
||||
cy.contains('Differential').click();
|
||||
cy.wait(500); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getIdFormField().type('Query3');
|
||||
inputQuery('select * from uptime;');
|
||||
cy.getBySel('resultsTypeField').click();
|
||||
cy.contains('Differential (Ignore removals)').click();
|
||||
cy.wait(500); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findAndClickButton('Save pack');
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.react('ScheduledQueryNameComponent', {
|
||||
props: {
|
||||
name: packName,
|
||||
},
|
||||
}).click();
|
||||
|
||||
findAndClickButton('Edit');
|
||||
cy.contains('Query1');
|
||||
cy.contains('Query2');
|
||||
cy.contains('Query3');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: 'Query1' } },
|
||||
}).click();
|
||||
cy.getBySel('resultsTypeField').contains('Snapshot').click();
|
||||
cy.contains('Differential').click();
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: 'Query2' } },
|
||||
}).click();
|
||||
cy.getBySel('resultsTypeField').contains('Differential').click();
|
||||
cy.contains('Differential (Ignore removals)').click();
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: 'Query3' } },
|
||||
}).click();
|
||||
cy.getBySel('resultsTypeField').contains('(Ignore removals)').click();
|
||||
cy.contains('Snapshot').click();
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findFormFieldByRowsLabelAndType(
|
||||
'Scheduled agent policies (optional)',
|
||||
'fleet server {downArrow} {enter}'
|
||||
);
|
||||
findAndClickButton('Update pack');
|
||||
closeModalIfVisible();
|
||||
|
||||
cy.contains(
|
||||
'Create packs to organize sets of queries and to schedule queries for agent policies.'
|
||||
);
|
||||
const queries = {
|
||||
Query1: {
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
removed: true,
|
||||
snapshot: false,
|
||||
},
|
||||
Query2: {
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
removed: false,
|
||||
snapshot: false,
|
||||
},
|
||||
Query3: {
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
},
|
||||
};
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
}).then((response) => {
|
||||
const item = response.body.items.find(
|
||||
(policy: PackagePolicy) => policy.policy_id === 'fleet-server-policy'
|
||||
);
|
||||
|
||||
expect(item?.inputs[0].config?.osquery.value.packs[packName].queries).to.deep.equal(
|
||||
queries
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Check if pack is created', () => {
|
||||
const packName = 'Pack-name' + generateRandomStringName(1)[0];
|
||||
let packId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
packId = pack;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('should add a pack from a saved query', () => {
|
||||
cy.contains('Packs').click();
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', packName);
|
||||
findFormFieldByRowsLabelAndType('Description (optional)', 'Pack description');
|
||||
findFormFieldByRowsLabelAndType('Scheduled agent policies (optional)', DEFAULT_POLICY);
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getSavedQueriesDropdown().type(`${savedQueryName}{downArrow}{enter}`);
|
||||
cy.react('EuiFormRow', { props: { label: 'Interval (s)' } })
|
||||
.click()
|
||||
.clear()
|
||||
.type('5');
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.react('EuiTableRow').contains(savedQueryName);
|
||||
findAndClickButton('Save pack');
|
||||
cy.contains('Save and deploy changes');
|
||||
findAndClickButton('Save and deploy changes');
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains(packName);
|
||||
cy.contains(`Successfully created "${packName}" pack`);
|
||||
closeToastIfVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('to click the edit button and edit pack', () => {
|
||||
const newQueryName = 'new-query-name' + generateRandomStringName(1)[0];
|
||||
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
cy.contains(`Edit ${packName}`);
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
inputQuery('select * from uptime');
|
||||
findFormFieldByRowsLabelAndType('ID', savedQueryName);
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.contains('ID must be unique').should('exist');
|
||||
findFormFieldByRowsLabelAndType('ID', newQueryName);
|
||||
cy.contains('ID must be unique').should('not.exist');
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.react('EuiTableRow').contains(newQueryName);
|
||||
findAndClickButton('Update pack');
|
||||
cy.contains('Save and deploy changes');
|
||||
findAndClickButton('Save and deploy changes');
|
||||
cy.contains(`Successfully updated "${packName}" pack`);
|
||||
closeToastIfVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should trigger validation when saved query is being chosen', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
cy.contains('ID must be unique').should('not.exist');
|
||||
getSavedQueriesDropdown().type(`${savedQueryName}{downArrow}{enter}`);
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.contains('ID must be unique').should('exist');
|
||||
cy.react('EuiFlyoutFooter').react('EuiButtonEmpty').contains('Cancel').click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should open lens in new tab', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
let lensUrl = '';
|
||||
cy.window().then((win) => {
|
||||
cy.stub(win, 'open')
|
||||
.as('windowOpen')
|
||||
.callsFake((url) => {
|
||||
lensUrl = url;
|
||||
});
|
||||
});
|
||||
preparePack(packName);
|
||||
cy.getBySel('docsLoading').should('exist');
|
||||
cy.getBySel('docsLoading').should('not.exist');
|
||||
cy.get(`[aria-label="View in Lens"]`).eq(0).click();
|
||||
cy.window()
|
||||
.its('open')
|
||||
.then(() => {
|
||||
cy.visit(lensUrl);
|
||||
});
|
||||
cy.getBySel('lnsWorkspace').should('exist');
|
||||
cy.getBySel('breadcrumbs').contains(`Action pack_${packName}_${savedQueryName}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('should open discover in new tab', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: savedQueryName } },
|
||||
})
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
cy.get('a')
|
||||
.should('have.attr', 'href')
|
||||
.then(($href) => {
|
||||
// @ts-expect-error-next-line href string - check types
|
||||
cy.visit($href);
|
||||
cy.getBySel('breadcrumbs').contains('Discover').should('exist');
|
||||
cy.contains(`action_id: pack_${PACK_NAME}_${savedQueryName}`);
|
||||
cy.getBySel('superDatePickerToggleQuickMenuButton').click();
|
||||
cy.getBySel('superDatePickerCommonlyUsed_Today').click();
|
||||
cy.getBySel('discoverDocTable', { timeout: 60000 }).contains(
|
||||
`pack_${PACK_NAME}_${savedQueryName}`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deactivate and activate pack', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
cy.contains('Packs').click();
|
||||
deactivatePack(packName);
|
||||
activatePack(packName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should verify that packs are triggered', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 60, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(`${packName} details`).should('exist');
|
||||
|
||||
recurse<string>(
|
||||
() => {
|
||||
cy.waitForReact();
|
||||
|
||||
cy.getBySel('docsLoading').should('exist');
|
||||
cy.getBySel('docsLoading').should('not.exist');
|
||||
|
||||
return cy.get('tbody .euiTableRow > td:nth-child(5)').invoke('text');
|
||||
},
|
||||
(response) => response === 'Docs1',
|
||||
{
|
||||
timeout: 300000,
|
||||
post: () => {
|
||||
cy.reload();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
cy.react('ScheduledQueryLastResults', { options: { timeout: 3000 } })
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
cy.react('FormattedRelative');
|
||||
});
|
||||
|
||||
cy.react('DocsColumnResults').within(() => {
|
||||
cy.react('EuiNotificationBadge').contains('1');
|
||||
});
|
||||
cy.react('AgentsColumnResults').within(() => {
|
||||
cy.react('EuiNotificationBadge').contains('1');
|
||||
});
|
||||
cy.getBySel('packResultsErrorsEmpty').should('have.length', 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete all queries in the pack', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(/^Edit$/).click();
|
||||
|
||||
cy.getBySel('checkboxSelectAll').click();
|
||||
|
||||
cy.contains(/^Delete \d+ quer(y|ies)/).click();
|
||||
cy.contains(/^Update pack$/).click();
|
||||
cy.react('EuiButtonDisplay')
|
||||
.contains(/^Save and deploy changes$/)
|
||||
.click();
|
||||
cy.get('a').contains(packName).click();
|
||||
cy.contains(`${packName} details`).should('exist');
|
||||
cy.contains(/^No items found/).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('enable changing saved queries and ecs_mappings', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(/^Edit$/).click();
|
||||
|
||||
findAndClickButton('Add query');
|
||||
|
||||
getSavedQueriesDropdown().type(`${multipleMappingsSavedQueryName} {downArrow} {enter}`);
|
||||
cy.contains('Custom key/value pairs').should('exist');
|
||||
cy.contains('Days of uptime').should('exist');
|
||||
cy.contains('List of keywords used to tag each').should('exist');
|
||||
cy.contains('Seconds of uptime').should('exist');
|
||||
cy.contains('Client network address.').should('exist');
|
||||
cy.contains('Total uptime seconds').should('exist');
|
||||
cy.getBySel('ECSMappingEditorForm').should('have.length', 4);
|
||||
|
||||
getSavedQueriesDropdown().type(`${nomappingSavedQueryName} {downArrow} {enter}`);
|
||||
cy.contains('Custom key/value pairs').should('not.exist');
|
||||
cy.contains('Days of uptime').should('not.exist');
|
||||
cy.contains('List of keywords used to tag each').should('not.exist');
|
||||
cy.contains('Seconds of uptime').should('not.exist');
|
||||
cy.contains('Client network address.').should('not.exist');
|
||||
cy.contains('Total uptime seconds').should('not.exist');
|
||||
cy.getBySel('ECSMappingEditorForm').should('have.length', 1);
|
||||
|
||||
getSavedQueriesDropdown().type(`${oneMappingSavedQueryName} {downArrow} {enter}`);
|
||||
cy.contains('Name of the continent').should('exist');
|
||||
cy.contains('Seconds of uptime').should('exist');
|
||||
cy.getBySel('ECSMappingEditorForm').should('have.length', 2);
|
||||
|
||||
findAndClickButton('Save');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: oneMappingSavedQueryName } },
|
||||
}).click();
|
||||
cy.contains('Name of the continent').should('exist');
|
||||
cy.contains('Seconds of uptime').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('to click delete button', () => {
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
deleteAndConfirm('pack');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Validate that agent policy is getting removed from pack if we remove agent policy', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
const AGENT_POLICY_NAME = `PackTest` + generateRandomStringName(1)[0];
|
||||
const REMOVING_PACK = 'removing-pack' + generateRandomStringName(1)[0];
|
||||
|
||||
it('add integration', () => {
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains('Create agent policy').click();
|
||||
cy.get('input[placeholder*="Choose a name"]').type(AGENT_POLICY_NAME);
|
||||
cy.get('.euiFlyoutFooter').contains('Create agent policy').click();
|
||||
cy.contains(`Agent policy '${AGENT_POLICY_NAME}' created`);
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains(AGENT_POLICY_NAME).click();
|
||||
cy.contains('Add integration').click();
|
||||
cy.contains(integration).click();
|
||||
addIntegration(AGENT_POLICY_NAME);
|
||||
cy.contains('Add Elastic Agent later').click();
|
||||
navigateTo('app/osquery/packs');
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', REMOVING_PACK);
|
||||
findFormFieldByRowsLabelAndType('Scheduled agent policies (optional)', AGENT_POLICY_NAME);
|
||||
findAndClickButton('Save pack');
|
||||
|
||||
closeToastIfVisible();
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.react('ScheduledQueryNameComponent', { props: { name: REMOVING_PACK } }).click();
|
||||
cy.contains(`${REMOVING_PACK} details`).should('exist');
|
||||
findAndClickButton('Edit');
|
||||
cy.react('EuiComboBoxInput', { props: { value: AGENT_POLICY_NAME } }).should('exist');
|
||||
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains(AGENT_POLICY_NAME).click();
|
||||
cy.get('.euiTableCellContent')
|
||||
.get('.euiPopover__anchor')
|
||||
.get(`[aria-label="Open"]`)
|
||||
.first()
|
||||
.click();
|
||||
cy.contains(/^Delete integration$/).click();
|
||||
closeModalIfVisible();
|
||||
cy.contains(/^Deleted integration 'osquery_manager-*/);
|
||||
navigateTo('app/osquery/packs');
|
||||
cy.contains(REMOVING_PACK).click();
|
||||
cy.contains(`${REMOVING_PACK} details`).should('exist');
|
||||
cy.wait(1000);
|
||||
findAndClickButton('Edit');
|
||||
cy.react('EuiComboBoxInput', { props: { value: '' } }).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Load prebuilt packs', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
navigateTo('/app/osquery/packs');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupAllPrebuiltPacks();
|
||||
});
|
||||
|
||||
const PREBUILD_PACK_NAME = 'it-compliance';
|
||||
|
||||
it('should load prebuilt packs', () => {
|
||||
cy.contains('Load Elastic prebuilt packs').click();
|
||||
cy.contains('Load Elastic prebuilt packs').should('not.exist');
|
||||
cy.wait(1000);
|
||||
cy.react('EuiTableRow').should('have.length.above', 5);
|
||||
});
|
||||
|
||||
it('should be able to activate pack', () => {
|
||||
activatePack(PREBUILD_PACK_NAME);
|
||||
deactivatePack(PREBUILD_PACK_NAME);
|
||||
});
|
||||
|
||||
it('should be able to add policy to it', () => {
|
||||
cy.contains(PREBUILD_PACK_NAME).click();
|
||||
cy.contains('Edit').click();
|
||||
findFormFieldByRowsLabelAndType(
|
||||
'Scheduled agent policies (optional)',
|
||||
'fleet server {downArrow}{enter}'
|
||||
);
|
||||
cy.contains('Update pack').click();
|
||||
cy.getBySel('confirmModalConfirmButton').click();
|
||||
cy.contains(`Successfully updated "${PREBUILD_PACK_NAME}" pack`);
|
||||
});
|
||||
|
||||
it('should be able to activate pack with agent inside', () => {
|
||||
activatePack(PREBUILD_PACK_NAME);
|
||||
deactivatePack(PREBUILD_PACK_NAME);
|
||||
});
|
||||
it('should not be able to update prebuilt pack', () => {
|
||||
cy.contains(PREBUILD_PACK_NAME).click();
|
||||
cy.contains('Edit').click();
|
||||
cy.react('EuiFieldText', { props: { name: 'name', isDisabled: true } });
|
||||
cy.react('EuiFieldText', { props: { name: 'description', isDisabled: true } });
|
||||
cy.contains('Add Query').should('not.exist');
|
||||
cy.react('ExpandedItemActions', { options: { timeout: 1000 } });
|
||||
cy.get('.euiTableRowCell--hasActions').should('not.exist');
|
||||
});
|
||||
it('should be able to delete prebuilt pack and add it again', () => {
|
||||
cy.contains(PREBUILD_PACK_NAME).click();
|
||||
cy.contains('Edit').click();
|
||||
deleteAndConfirm('pack');
|
||||
cy.contains(PREBUILD_PACK_NAME).should('not.exist');
|
||||
cy.contains('Update Elastic prebuilt packs').click();
|
||||
cy.contains('Successfully updated prebuilt packs');
|
||||
cy.contains(PREBUILD_PACK_NAME).should('exist');
|
||||
});
|
||||
|
||||
it('should be able to run live prebuilt pack', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
cy.contains('New live query').click();
|
||||
cy.contains('Run a set of queries in a pack.').click();
|
||||
cy.get(LIVE_QUERY_EDITOR).should('not.exist');
|
||||
cy.getBySel('select-live-pack').click().type('osquery-monitoring{downArrow}{enter}');
|
||||
selectAllAgents();
|
||||
submitQuery();
|
||||
cy.getBySel('live-query-loading').should('exist');
|
||||
cy.getBySel('live-query-loading', { timeout: 10000 }).should('not.exist');
|
||||
cy.getBySel('toggleIcon-events').click();
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
navigateTo('/app/osquery');
|
||||
cy.contains('osquery-monitoring');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Global packs', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
navigateTo('/app/osquery/packs');
|
||||
});
|
||||
|
||||
describe('add proper shard to policies packs config', () => {
|
||||
const globalPack = 'globalPack' + generateRandomStringName(1)[0];
|
||||
const agentPolicy = 'testGlobal' + generateRandomStringName(1)[0];
|
||||
let globalPackId: string;
|
||||
let agentPolicyId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
globalPackId = pack;
|
||||
});
|
||||
interceptAgentPolicyId((policyId) => {
|
||||
agentPolicyId = policyId;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(globalPackId);
|
||||
cleanupAgentPolicy(agentPolicyId);
|
||||
});
|
||||
|
||||
it('add global packs to policies', () => {
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', globalPack);
|
||||
cy.getBySel('policyIdsComboBox').should('exist');
|
||||
cy.getBySel('osqueryPackTypeGlobal').click();
|
||||
cy.getBySel('policyIdsComboBox').should('not.exist');
|
||||
|
||||
findAndClickButton('Save pack');
|
||||
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains(globalPack);
|
||||
cy.contains(`Successfully created "${globalPack}" pack`);
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains('Create agent policy').click();
|
||||
cy.getBySel('createAgentPolicyNameField').type(agentPolicy);
|
||||
cy.getBySel('createAgentPolicyFlyoutBtn').click();
|
||||
cy.contains(`Agent policy '${agentPolicy}' created`).click();
|
||||
cy.contains(agentPolicy).click();
|
||||
cy.contains('Add integration').click();
|
||||
cy.contains(integration).click();
|
||||
addIntegration(agentPolicy);
|
||||
cy.contains('Add Elastic Agent later').click();
|
||||
cy.contains('osquery_manager-');
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
}).then((response) => {
|
||||
const item = find(response.body.items, ['policy_id', agentPolicyId]);
|
||||
|
||||
expect(item?.inputs[0].config?.osquery.value.packs[globalPack]).to.deep.equal({
|
||||
shard: 100,
|
||||
queries: {},
|
||||
});
|
||||
});
|
||||
cy.visit('/app/fleet/policies');
|
||||
cy.contains('td', agentPolicy)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.contains('rev. 2').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('add proper shard to policies packs config', () => {
|
||||
let shardPackId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
shardPackId = pack;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(shardPackId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
const shardPack = 'shardPack' + generateRandomStringName(1)[0];
|
||||
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', shardPack);
|
||||
|
||||
cy.contains('Partial deployment (shards)').click();
|
||||
cy.getBySel('packShardsForm-0').within(() => {
|
||||
cy.getBySel('shards-field-policy').type(`${DEFAULT_POLICY}{downArrow}{enter}`);
|
||||
cy.get('#shardsPercentage0').type('{backspace}{backspace}5');
|
||||
});
|
||||
cy.getBySel('packShardsForm-1').within(() => {
|
||||
cy.getBySel('shards-field-policy').type(`${OSQUERY_POLICY}{downArrow}{enter}`);
|
||||
cy.get('#shardsPercentage1').type('{backspace}{backspace}{backspace}');
|
||||
});
|
||||
findAndClickButton('Save pack');
|
||||
|
||||
cy.contains(`Successfully created "${shardPack}" pack`);
|
||||
closeToastIfVisible();
|
||||
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
}).then((response) => {
|
||||
const shardPolicy = response.body.items.find(
|
||||
(policy: PackagePolicy) => policy.policy_id === 'fleet-server-policy'
|
||||
);
|
||||
|
||||
expect(shardPolicy?.inputs[0].config?.osquery.value.packs[shardPack]).to.deep.equal({
|
||||
shard: 15,
|
||||
queries: {},
|
||||
});
|
||||
});
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains(shardPack).click();
|
||||
cy.contains('Edit').click();
|
||||
cy.get('#shardsPercentage0').should('have.value', '15');
|
||||
cy.getBySel('packShardsForm-1').within(() => {
|
||||
cy.getBySel('shards-field-policy').contains(OSQUERY_POLICY);
|
||||
cy.get('#shardsPercentage1').should('have.value', '0');
|
||||
});
|
||||
cy.getBySel('policyIdsComboBox').within(() => {
|
||||
cy.contains(OSQUERY_POLICY).should('not.exist');
|
||||
});
|
||||
|
||||
cy.getBySel('comboBoxInput').contains(OSQUERY_POLICY).should('exist');
|
||||
cy.getBySel('policyIdsComboBox').click();
|
||||
cy.get('[data-test-subj="packShardsForm-1"]').within(() => {
|
||||
cy.get(`[aria-label="Delete shards row"]`).click();
|
||||
});
|
||||
cy.getBySel('comboBoxInput').contains(OSQUERY_POLICY).should('not.exist');
|
||||
cy.getBySel('policyIdsComboBox').click();
|
||||
cy.contains(OSQUERY_POLICY).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
628
x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts
Normal file
628
x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts
Normal file
|
@ -0,0 +1,628 @@
|
|||
/*
|
||||
* 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 type { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { API_VERSIONS } from '../../../common/constants';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
deleteAndConfirm,
|
||||
findAndClickButton,
|
||||
findFormFieldByRowsLabelAndType,
|
||||
inputQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { activatePack, deactivatePack, preparePack } from '../../tasks/packs';
|
||||
import {
|
||||
closeModalIfVisible,
|
||||
closeToastIfVisible,
|
||||
generateRandomStringName,
|
||||
interceptPackId,
|
||||
} from '../../tasks/integrations';
|
||||
import { DEFAULT_POLICY } from '../../screens/fleet';
|
||||
import { getIdFormField, getSavedQueriesDropdown } from '../../screens/live_query';
|
||||
import { loadSavedQuery, cleanupSavedQuery, cleanupPack, loadPack } from '../../tasks/api_fixtures';
|
||||
import { request } from '../../tasks/common';
|
||||
|
||||
describe('Packs - Create and Edit', () => {
|
||||
let savedQueryId: string;
|
||||
let savedQueryName: string;
|
||||
let nomappingSavedQueryId: string;
|
||||
let nomappingSavedQueryName: string;
|
||||
let oneMappingSavedQueryId: string;
|
||||
let oneMappingSavedQueryName: string;
|
||||
let multipleMappingsSavedQueryId: string;
|
||||
let multipleMappingsSavedQueryName: string;
|
||||
|
||||
const PACK_NAME = 'Pack-name' + generateRandomStringName(1)[0];
|
||||
|
||||
before(() => {
|
||||
loadSavedQuery().then((data) => {
|
||||
savedQueryId = data.saved_object_id;
|
||||
savedQueryName = data.id;
|
||||
});
|
||||
loadSavedQuery({
|
||||
ecs_mapping: {},
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
}).then((data) => {
|
||||
nomappingSavedQueryId = data.saved_object_id;
|
||||
nomappingSavedQueryName = data.id;
|
||||
});
|
||||
loadSavedQuery({
|
||||
ecs_mapping: {
|
||||
'client.geo.continent_name': {
|
||||
field: 'seconds',
|
||||
},
|
||||
},
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
}).then((data) => {
|
||||
oneMappingSavedQueryId = data.saved_object_id;
|
||||
oneMappingSavedQueryName = data.id;
|
||||
});
|
||||
loadSavedQuery({
|
||||
ecs_mapping: {
|
||||
labels: {
|
||||
field: 'days',
|
||||
},
|
||||
tags: {
|
||||
field: 'seconds',
|
||||
},
|
||||
'client.address': {
|
||||
field: 'total_seconds',
|
||||
},
|
||||
},
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
}).then((data) => {
|
||||
multipleMappingsSavedQueryId = data.saved_object_id;
|
||||
multipleMappingsSavedQueryName = data.id;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
cleanupSavedQuery(nomappingSavedQueryId);
|
||||
cleanupSavedQuery(oneMappingSavedQueryId);
|
||||
cleanupSavedQuery(multipleMappingsSavedQueryId);
|
||||
});
|
||||
|
||||
describe('Check if result type is correct', () => {
|
||||
let resultTypePackId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
resultTypePackId = pack;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(resultTypePackId);
|
||||
});
|
||||
|
||||
it('Check if result type is correct', () => {
|
||||
const packName = 'ResultType' + generateRandomStringName(1)[0];
|
||||
|
||||
cy.contains('Packs').click();
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', packName);
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getIdFormField().type('Query1');
|
||||
inputQuery('select * from uptime;');
|
||||
cy.wait(500); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getIdFormField().type('Query2');
|
||||
inputQuery('select * from uptime;');
|
||||
|
||||
cy.getBySel('resultsTypeField').click();
|
||||
cy.contains('Differential').click();
|
||||
cy.wait(500); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getIdFormField().type('Query3');
|
||||
inputQuery('select * from uptime;');
|
||||
cy.getBySel('resultsTypeField').click();
|
||||
cy.contains('Differential (Ignore removals)').click();
|
||||
cy.wait(500); // wait for the validation to trigger - cypress is way faster than users ;)
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findAndClickButton('Save pack');
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.react('ScheduledQueryNameComponent', {
|
||||
props: {
|
||||
name: packName,
|
||||
},
|
||||
}).click();
|
||||
|
||||
findAndClickButton('Edit');
|
||||
cy.contains('Query1');
|
||||
cy.contains('Query2');
|
||||
cy.contains('Query3');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: 'Query1' } },
|
||||
}).click();
|
||||
cy.getBySel('resultsTypeField').contains('Snapshot').click();
|
||||
cy.contains('Differential').click();
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: 'Query2' } },
|
||||
}).click();
|
||||
cy.getBySel('resultsTypeField').contains('Differential').click();
|
||||
cy.contains('Differential (Ignore removals)').click();
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: 'Query3' } },
|
||||
}).click();
|
||||
cy.getBySel('resultsTypeField').contains('(Ignore removals)').click();
|
||||
cy.contains('Snapshot').click();
|
||||
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
findFormFieldByRowsLabelAndType(
|
||||
'Scheduled agent policies (optional)',
|
||||
'fleet server {downArrow} {enter}'
|
||||
);
|
||||
findAndClickButton('Update pack');
|
||||
closeModalIfVisible();
|
||||
|
||||
cy.contains(
|
||||
'Create packs to organize sets of queries and to schedule queries for agent policies.'
|
||||
);
|
||||
const queries = {
|
||||
Query1: {
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
removed: true,
|
||||
snapshot: false,
|
||||
},
|
||||
Query2: {
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
removed: false,
|
||||
snapshot: false,
|
||||
},
|
||||
Query3: {
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
},
|
||||
};
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
}).then((response) => {
|
||||
const item = response.body.items.find(
|
||||
(policy: PackagePolicy) => policy.policy_id === 'fleet-server-policy'
|
||||
);
|
||||
|
||||
expect(item?.inputs[0].config?.osquery.value.packs[packName].queries).to.deep.equal(
|
||||
queries
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Check if pack is created', () => {
|
||||
const packName = 'Pack-name' + generateRandomStringName(1)[0];
|
||||
let packId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
packId = pack;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('should add a pack from a saved query', () => {
|
||||
cy.contains('Packs').click();
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', packName);
|
||||
findFormFieldByRowsLabelAndType('Description (optional)', 'Pack description');
|
||||
findFormFieldByRowsLabelAndType('Scheduled agent policies (optional)', DEFAULT_POLICY);
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
getSavedQueriesDropdown().type(`${savedQueryName}{downArrow}{enter}`);
|
||||
cy.react('EuiFormRow', { props: { label: 'Interval (s)' } })
|
||||
.click()
|
||||
.clear()
|
||||
.type('5');
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.react('EuiTableRow').contains(savedQueryName);
|
||||
findAndClickButton('Save pack');
|
||||
cy.contains('Save and deploy changes');
|
||||
findAndClickButton('Save and deploy changes');
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains(packName);
|
||||
cy.contains(`Successfully created "${packName}" pack`);
|
||||
closeToastIfVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('to click the edit button and edit pack', () => {
|
||||
const newQueryName = 'new-query-name' + generateRandomStringName(1)[0];
|
||||
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
cy.contains(`Edit ${packName}`);
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
inputQuery('select * from uptime');
|
||||
findFormFieldByRowsLabelAndType('ID', savedQueryName);
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.contains('ID must be unique').should('exist');
|
||||
findFormFieldByRowsLabelAndType('ID', newQueryName);
|
||||
cy.contains('ID must be unique').should('not.exist');
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.react('EuiTableRow').contains(newQueryName);
|
||||
findAndClickButton('Update pack');
|
||||
cy.contains('Save and deploy changes');
|
||||
findAndClickButton('Save and deploy changes');
|
||||
cy.contains(`Successfully updated "${packName}" pack`);
|
||||
closeToastIfVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should trigger validation when saved query is being chosen', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
findAndClickButton('Add query');
|
||||
cy.contains('Attach next query');
|
||||
cy.contains('ID must be unique').should('not.exist');
|
||||
getSavedQueriesDropdown().type(`${savedQueryName}{downArrow}{enter}`);
|
||||
cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click();
|
||||
cy.contains('ID must be unique').should('exist');
|
||||
cy.react('EuiFlyoutFooter').react('EuiButtonEmpty').contains('Cancel').click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should open lens in new tab', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
let lensUrl = '';
|
||||
cy.window().then((win) => {
|
||||
cy.stub(win, 'open')
|
||||
.as('windowOpen')
|
||||
.callsFake((url) => {
|
||||
lensUrl = url;
|
||||
});
|
||||
});
|
||||
preparePack(packName);
|
||||
cy.getBySel('docsLoading').should('exist');
|
||||
cy.getBySel('docsLoading').should('not.exist');
|
||||
cy.get(`[aria-label="View in Lens"]`).eq(0).click();
|
||||
cy.window()
|
||||
.its('open')
|
||||
.then(() => {
|
||||
cy.visit(lensUrl);
|
||||
});
|
||||
cy.getBySel('lnsWorkspace').should('exist');
|
||||
cy.getBySel('breadcrumbs').contains(`Action pack_${packName}_${savedQueryName}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('should open discover in new tab', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: savedQueryName } },
|
||||
})
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
cy.get('a')
|
||||
.should('have.attr', 'href')
|
||||
.then(($href) => {
|
||||
// @ts-expect-error-next-line href string - check types
|
||||
cy.visit($href);
|
||||
cy.getBySel('breadcrumbs').contains('Discover').should('exist');
|
||||
cy.contains(`action_id: pack_${PACK_NAME}_${savedQueryName}`);
|
||||
cy.getBySel('superDatePickerToggleQuickMenuButton').click();
|
||||
cy.getBySel('superDatePickerCommonlyUsed_Today').click();
|
||||
cy.getBySel('discoverDocTable', { timeout: 60000 }).contains(
|
||||
`pack_${PACK_NAME}_${savedQueryName}`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deactivate and activate pack', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
cy.contains('Packs').click();
|
||||
deactivatePack(packName);
|
||||
activatePack(packName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should verify that packs are triggered', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 60, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(`${packName} details`).should('exist');
|
||||
|
||||
recurse<string>(
|
||||
() => {
|
||||
cy.waitForReact();
|
||||
|
||||
cy.getBySel('docsLoading').should('exist');
|
||||
cy.getBySel('docsLoading').should('not.exist');
|
||||
|
||||
return cy.get('tbody .euiTableRow > td:nth-child(5)').invoke('text');
|
||||
},
|
||||
(response) => response === 'Docs1',
|
||||
{
|
||||
timeout: 300000,
|
||||
post: () => {
|
||||
cy.reload();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
cy.react('ScheduledQueryLastResults', { options: { timeout: 3000 } })
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
cy.react('FormattedRelative');
|
||||
});
|
||||
|
||||
cy.react('DocsColumnResults').within(() => {
|
||||
cy.react('EuiNotificationBadge').contains('1');
|
||||
});
|
||||
cy.react('AgentsColumnResults').within(() => {
|
||||
cy.react('EuiNotificationBadge').contains('1');
|
||||
});
|
||||
cy.getBySel('packResultsErrorsEmpty').should('have.length', 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete all queries in the pack', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(/^Edit$/).click();
|
||||
|
||||
cy.getBySel('checkboxSelectAll').click();
|
||||
|
||||
cy.contains(/^Delete \d+ quer(y|ies)/).click();
|
||||
cy.contains(/^Update pack$/).click();
|
||||
cy.react('EuiButtonDisplay')
|
||||
.contains(/^Save and deploy changes$/)
|
||||
.click();
|
||||
cy.get('a').contains(packName).click();
|
||||
cy.contains(`${packName} details`).should('exist');
|
||||
cy.contains(/^No items found/).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('enable changing saved queries and ecs_mappings', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(/^Edit$/).click();
|
||||
|
||||
findAndClickButton('Add query');
|
||||
|
||||
getSavedQueriesDropdown().type(`${multipleMappingsSavedQueryName} {downArrow} {enter}`);
|
||||
cy.contains('Custom key/value pairs').should('exist');
|
||||
cy.contains('Days of uptime').should('exist');
|
||||
cy.contains('List of keywords used to tag each').should('exist');
|
||||
cy.contains('Seconds of uptime').should('exist');
|
||||
cy.contains('Client network address.').should('exist');
|
||||
cy.contains('Total uptime seconds').should('exist');
|
||||
cy.getBySel('ECSMappingEditorForm').should('have.length', 4);
|
||||
|
||||
getSavedQueriesDropdown().type(`${nomappingSavedQueryName} {downArrow} {enter}`);
|
||||
cy.contains('Custom key/value pairs').should('not.exist');
|
||||
cy.contains('Days of uptime').should('not.exist');
|
||||
cy.contains('List of keywords used to tag each').should('not.exist');
|
||||
cy.contains('Seconds of uptime').should('not.exist');
|
||||
cy.contains('Client network address.').should('not.exist');
|
||||
cy.contains('Total uptime seconds').should('not.exist');
|
||||
cy.getBySel('ECSMappingEditorForm').should('have.length', 1);
|
||||
|
||||
getSavedQueriesDropdown().type(`${oneMappingSavedQueryName} {downArrow} {enter}`);
|
||||
cy.contains('Name of the continent').should('exist');
|
||||
cy.contains('Seconds of uptime').should('exist');
|
||||
cy.getBySel('ECSMappingEditorForm').should('have.length', 2);
|
||||
|
||||
findAndClickButton('Save');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: oneMappingSavedQueryName } },
|
||||
}).click();
|
||||
cy.contains('Name of the continent').should('exist');
|
||||
cy.contains('Seconds of uptime').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('to click delete button', () => {
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
policy_ids: ['fleet-server-policy'],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
}).then((pack) => {
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
deleteAndConfirm('pack');
|
||||
});
|
||||
});
|
||||
});
|
319
x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts
Normal file
319
x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* 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 { find } from 'lodash';
|
||||
import type { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { API_VERSIONS } from '../../../common/constants';
|
||||
import { FLEET_AGENT_POLICIES, navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
deleteAndConfirm,
|
||||
findAndClickButton,
|
||||
findFormFieldByRowsLabelAndType,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { activatePack, cleanupAllPrebuiltPacks, deactivatePack } from '../../tasks/packs';
|
||||
import {
|
||||
addIntegration,
|
||||
closeModalIfVisible,
|
||||
closeToastIfVisible,
|
||||
generateRandomStringName,
|
||||
interceptPackId,
|
||||
interceptAgentPolicyId,
|
||||
} from '../../tasks/integrations';
|
||||
import { DEFAULT_POLICY, OSQUERY_POLICY } from '../../screens/fleet';
|
||||
import { LIVE_QUERY_EDITOR } from '../../screens/live_query';
|
||||
import { cleanupPack, cleanupAgentPolicy } from '../../tasks/api_fixtures';
|
||||
import { request } from '../../tasks/common';
|
||||
|
||||
describe('ALL - Packs', () => {
|
||||
const integration = 'Osquery Manager';
|
||||
|
||||
describe('Validate that agent policy is getting removed from pack if we remove agent policy', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
const AGENT_POLICY_NAME = `PackTest` + generateRandomStringName(1)[0];
|
||||
const REMOVING_PACK = 'removing-pack' + generateRandomStringName(1)[0];
|
||||
|
||||
it('add integration', () => {
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains('Create agent policy').click();
|
||||
cy.get('input[placeholder*="Choose a name"]').type(AGENT_POLICY_NAME);
|
||||
cy.get('.euiFlyoutFooter').contains('Create agent policy').click();
|
||||
cy.contains(`Agent policy '${AGENT_POLICY_NAME}' created`);
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains(AGENT_POLICY_NAME).click();
|
||||
cy.contains('Add integration').click();
|
||||
cy.contains(integration).click();
|
||||
addIntegration(AGENT_POLICY_NAME);
|
||||
cy.contains('Add Elastic Agent later').click();
|
||||
navigateTo('app/osquery/packs');
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', REMOVING_PACK);
|
||||
findFormFieldByRowsLabelAndType('Scheduled agent policies (optional)', AGENT_POLICY_NAME);
|
||||
findAndClickButton('Save pack');
|
||||
|
||||
closeToastIfVisible();
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.react('ScheduledQueryNameComponent', { props: { name: REMOVING_PACK } }).click();
|
||||
cy.contains(`${REMOVING_PACK} details`).should('exist');
|
||||
findAndClickButton('Edit');
|
||||
cy.react('EuiComboBoxInput', { props: { value: AGENT_POLICY_NAME } }).should('exist');
|
||||
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains(AGENT_POLICY_NAME).click();
|
||||
cy.get('.euiTableCellContent')
|
||||
.get('.euiPopover__anchor')
|
||||
.get(`[aria-label="Open"]`)
|
||||
.first()
|
||||
.click();
|
||||
cy.contains(/^Delete integration$/).click();
|
||||
closeModalIfVisible();
|
||||
cy.contains(/^Deleted integration 'osquery_manager-*/);
|
||||
navigateTo('app/osquery/packs');
|
||||
cy.contains(REMOVING_PACK).click();
|
||||
cy.contains(`${REMOVING_PACK} details`).should('exist');
|
||||
cy.wait(1000);
|
||||
findAndClickButton('Edit');
|
||||
cy.react('EuiComboBoxInput', { props: { value: '' } }).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Load prebuilt packs', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
navigateTo('/app/osquery/packs');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupAllPrebuiltPacks();
|
||||
});
|
||||
|
||||
const PREBUILD_PACK_NAME = 'it-compliance';
|
||||
|
||||
it('should load prebuilt packs', () => {
|
||||
cy.contains('Load Elastic prebuilt packs').click();
|
||||
cy.contains('Load Elastic prebuilt packs').should('not.exist');
|
||||
cy.wait(1000);
|
||||
cy.react('EuiTableRow').should('have.length.above', 5);
|
||||
});
|
||||
|
||||
it('should be able to activate pack', () => {
|
||||
activatePack(PREBUILD_PACK_NAME);
|
||||
deactivatePack(PREBUILD_PACK_NAME);
|
||||
});
|
||||
|
||||
it('should be able to add policy to it', () => {
|
||||
cy.contains(PREBUILD_PACK_NAME).click();
|
||||
cy.contains('Edit').click();
|
||||
findFormFieldByRowsLabelAndType(
|
||||
'Scheduled agent policies (optional)',
|
||||
'fleet server {downArrow}{enter}'
|
||||
);
|
||||
cy.contains('Update pack').click();
|
||||
cy.getBySel('confirmModalConfirmButton').click();
|
||||
cy.contains(`Successfully updated "${PREBUILD_PACK_NAME}" pack`);
|
||||
});
|
||||
|
||||
it('should be able to activate pack with agent inside', () => {
|
||||
activatePack(PREBUILD_PACK_NAME);
|
||||
deactivatePack(PREBUILD_PACK_NAME);
|
||||
});
|
||||
it('should not be able to update prebuilt pack', () => {
|
||||
cy.contains(PREBUILD_PACK_NAME).click();
|
||||
cy.contains('Edit').click();
|
||||
cy.react('EuiFieldText', { props: { name: 'name', isDisabled: true } });
|
||||
cy.react('EuiFieldText', { props: { name: 'description', isDisabled: true } });
|
||||
cy.contains('Add Query').should('not.exist');
|
||||
cy.react('ExpandedItemActions', { options: { timeout: 1000 } });
|
||||
cy.get('.euiTableRowCell--hasActions').should('not.exist');
|
||||
});
|
||||
it('should be able to delete prebuilt pack and add it again', () => {
|
||||
cy.contains(PREBUILD_PACK_NAME).click();
|
||||
cy.contains('Edit').click();
|
||||
deleteAndConfirm('pack');
|
||||
cy.contains(PREBUILD_PACK_NAME).should('not.exist');
|
||||
cy.contains('Update Elastic prebuilt packs').click();
|
||||
cy.contains('Successfully updated prebuilt packs');
|
||||
cy.contains(PREBUILD_PACK_NAME).should('exist');
|
||||
});
|
||||
|
||||
it('should be able to run live prebuilt pack', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
cy.contains('New live query').click();
|
||||
cy.contains('Run a set of queries in a pack.').click();
|
||||
cy.get(LIVE_QUERY_EDITOR).should('not.exist');
|
||||
cy.getBySel('select-live-pack').click().type('osquery-monitoring{downArrow}{enter}');
|
||||
selectAllAgents();
|
||||
submitQuery();
|
||||
cy.getBySel('live-query-loading').should('exist');
|
||||
cy.getBySel('live-query-loading', { timeout: 10000 }).should('not.exist');
|
||||
cy.getBySel('toggleIcon-events').click();
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
navigateTo('/app/osquery');
|
||||
cy.contains('osquery-monitoring');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Global packs', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
navigateTo('/app/osquery/packs');
|
||||
});
|
||||
|
||||
describe('add proper shard to policies packs config', () => {
|
||||
const globalPack = 'globalPack' + generateRandomStringName(1)[0];
|
||||
const agentPolicy = 'testGlobal' + generateRandomStringName(1)[0];
|
||||
let globalPackId: string;
|
||||
let agentPolicyId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
globalPackId = pack;
|
||||
});
|
||||
interceptAgentPolicyId((policyId) => {
|
||||
agentPolicyId = policyId;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(globalPackId);
|
||||
cleanupAgentPolicy(agentPolicyId);
|
||||
});
|
||||
|
||||
it('add global packs to policies', () => {
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', globalPack);
|
||||
cy.getBySel('policyIdsComboBox').should('exist');
|
||||
cy.getBySel('osqueryPackTypeGlobal').click();
|
||||
cy.getBySel('policyIdsComboBox').should('not.exist');
|
||||
|
||||
findAndClickButton('Save pack');
|
||||
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains(globalPack);
|
||||
cy.contains(`Successfully created "${globalPack}" pack`);
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.visit(FLEET_AGENT_POLICIES);
|
||||
cy.contains('Create agent policy').click();
|
||||
cy.getBySel('createAgentPolicyNameField').type(agentPolicy);
|
||||
cy.getBySel('createAgentPolicyFlyoutBtn').click();
|
||||
cy.contains(`Agent policy '${agentPolicy}' created`).click();
|
||||
cy.contains(agentPolicy).click();
|
||||
cy.contains('Add integration').click();
|
||||
cy.contains(integration).click();
|
||||
addIntegration(agentPolicy);
|
||||
cy.contains('Add Elastic Agent later').click();
|
||||
cy.contains('osquery_manager-');
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
}).then((response) => {
|
||||
const item = find(response.body.items, ['policy_id', agentPolicyId]);
|
||||
|
||||
expect(item?.inputs[0].config?.osquery.value.packs[globalPack]).to.deep.equal({
|
||||
shard: 100,
|
||||
queries: {},
|
||||
});
|
||||
});
|
||||
cy.visit('/app/fleet/policies');
|
||||
cy.contains('td', agentPolicy)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.contains('rev. 2').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('add proper shard to policies packs config', () => {
|
||||
let shardPackId: string;
|
||||
|
||||
before(() => {
|
||||
interceptPackId((pack) => {
|
||||
shardPackId = pack;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(shardPackId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
const shardPack = 'shardPack' + generateRandomStringName(1)[0];
|
||||
|
||||
findAndClickButton('Add pack');
|
||||
findFormFieldByRowsLabelAndType('Name', shardPack);
|
||||
|
||||
cy.contains('Partial deployment (shards)').click();
|
||||
cy.getBySel('packShardsForm-0').within(() => {
|
||||
cy.getBySel('shards-field-policy').type(`${DEFAULT_POLICY}{downArrow}{enter}`);
|
||||
cy.get('#shardsPercentage0').type('{backspace}{backspace}5');
|
||||
});
|
||||
cy.getBySel('packShardsForm-1').within(() => {
|
||||
cy.getBySel('shards-field-policy').type(`${OSQUERY_POLICY}{downArrow}{enter}`);
|
||||
cy.get('#shardsPercentage1').type('{backspace}{backspace}{backspace}');
|
||||
});
|
||||
findAndClickButton('Save pack');
|
||||
|
||||
cy.contains(`Successfully created "${shardPack}" pack`);
|
||||
closeToastIfVisible();
|
||||
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
}).then((response) => {
|
||||
const shardPolicy = response.body.items.find(
|
||||
(policy: PackagePolicy) => policy.policy_id === 'fleet-server-policy'
|
||||
);
|
||||
|
||||
expect(shardPolicy?.inputs[0].config?.osquery.value.packs[shardPack]).to.deep.equal({
|
||||
shard: 15,
|
||||
queries: {},
|
||||
});
|
||||
});
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains(shardPack).click();
|
||||
cy.contains('Edit').click();
|
||||
cy.get('#shardsPercentage0').should('have.value', '15');
|
||||
cy.getBySel('packShardsForm-1').within(() => {
|
||||
cy.getBySel('shards-field-policy').contains(OSQUERY_POLICY);
|
||||
cy.get('#shardsPercentage1').should('have.value', '0');
|
||||
});
|
||||
cy.getBySel('policyIdsComboBox').within(() => {
|
||||
cy.contains(OSQUERY_POLICY).should('not.exist');
|
||||
});
|
||||
|
||||
cy.getBySel('comboBoxInput').contains(OSQUERY_POLICY).should('exist');
|
||||
cy.getBySel('policyIdsComboBox').click();
|
||||
cy.get('[data-test-subj="packShardsForm-1"]').within(() => {
|
||||
cy.get(`[aria-label="Delete shards row"]`).click();
|
||||
});
|
||||
cy.getBySel('comboBoxInput').contains(OSQUERY_POLICY).should('not.exist');
|
||||
cy.getBySel('policyIdsComboBox').click();
|
||||
cy.contains(OSQUERY_POLICY).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -97,6 +97,7 @@ describe('Alert Test', () => {
|
|||
cy.getBySel('expand-event').first().click();
|
||||
|
||||
cy.wait(500);
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutInvestigationGuideButton').click();
|
||||
cy.contains('Get processes').click();
|
||||
});
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ describe('None', () => {
|
|||
cy.visit(`/app/security/rules/id/${ruleId}/alerts`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('responseActionsViewTab').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.contains('Permission denied').should('exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
export {};
|
||||
|
||||
import 'cypress-react-selector';
|
||||
// import './coverage';
|
||||
import registerCypressGrep from '@cypress/grep';
|
||||
|
||||
registerCypressGrep();
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
|
|
|
@ -229,6 +229,7 @@ export const cleanupCase = (id: string) => {
|
|||
method: 'DELETE',
|
||||
url: '/api/cases',
|
||||
qs: { ids: JSON.stringify([id]) },
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { LIVE_QUERY_EDITOR } from '../screens/live_query';
|
||||
import { ROLE, login } from './login';
|
||||
|
||||
export const DEFAULT_QUERY = 'select * from processes;';
|
||||
export const BIG_QUERY = 'select * from processes, users limit 110;';
|
||||
|
@ -100,6 +101,7 @@ export const toggleRuleOffAndOn = (ruleName: string) => {
|
|||
};
|
||||
|
||||
export const loadRuleAlerts = (ruleName: string) => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
cy.getBySel('alertsTable').within(() => {
|
||||
|
|
|
@ -5,8 +5,12 @@
|
|||
"private": true,
|
||||
"license": "Elastic License 2.0",
|
||||
"scripts": {
|
||||
"cypress:burn": "yarn cypress:run --env burn=2 --concurrency=1 --headed",
|
||||
"cypress:changed-specs-only": "yarn cypress:run --changed-specs-only --env burn=2",
|
||||
"cypress:open": "node ../security_solution/scripts/start_cypress_parallel open --config-file ../osquery/cypress.config.ts --ftr-config-file ../../../x-pack/test/osquery_cypress/cli_config",
|
||||
"cypress:run": "node ../security_solution/scripts/start_cypress_parallel run --config-file ../osquery/cypress.config.ts --ftr-config-file ../../../x-pack/test/osquery_cypress/cli_config --concurrency 1",
|
||||
"nyc": "../../../node_modules/.bin/nyc report --reporter=text-summary"
|
||||
"nyc": "../../../node_modules/.bin/nyc report --reporter=text-summary",
|
||||
"junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-osquery/cypress/results/mochawesome*.json > ../../../target/kibana-osquery/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-osquery/cypress/results/output.json --reportDir ../../../target/kibana-osquery/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-osquery/cypress/results/*.xml ../../../target/junit/",
|
||||
"junit:transform": "node ../security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-osquery/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Osquery Cypress' --writeInPlace"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { pick } from 'lodash';
|
||||
import { map, pick } from 'lodash';
|
||||
import type { Client, estypes } from '@elastic/elasticsearch';
|
||||
import type {
|
||||
Agent,
|
||||
|
@ -35,6 +35,7 @@ import type {
|
|||
} from '@kbn/fleet-plugin/common/types';
|
||||
import nodeFetch from 'node-fetch';
|
||||
import semver from 'semver';
|
||||
import axios from 'axios';
|
||||
import { catchAxiosErrorFormatAndThrow } from './format_axios_error';
|
||||
import { FleetAgentGenerator } from '../../../common/endpoint/data_generators/fleet_agent_generator';
|
||||
|
||||
|
@ -236,7 +237,13 @@ export const getAgentVersionMatchingCurrentStack = async (
|
|||
kbnClient: KbnClient
|
||||
): Promise<string> => {
|
||||
const kbnStatus = await kbnClient.status.get();
|
||||
let version = kbnStatus.version.number;
|
||||
const agentVersions = await axios
|
||||
.get('https://artifacts-api.elastic.co/v1/versions')
|
||||
.then((response) => map(response.data.versions, (version) => version.split('-SNAPSHOT')[0]));
|
||||
|
||||
let version =
|
||||
semver.maxSatisfying(agentVersions, `<=${kbnStatus.version.number}`) ??
|
||||
kbnStatus.version.number;
|
||||
|
||||
// Add `-SNAPSHOT` if version indicates it was from a snapshot or the build hash starts
|
||||
// with `xxxxxxxxx` (value that seems to be present when running kibana from source)
|
||||
|
|
|
@ -105,6 +105,10 @@ export const cli = () => {
|
|||
// eslint-disable-next-line no-process-exit
|
||||
return process.exit(0);
|
||||
}
|
||||
|
||||
// to avoid running too many tests, we limit the number of files to 3
|
||||
// we may extend this in the future
|
||||
files = files.slice(0, 3);
|
||||
}
|
||||
|
||||
if (!files?.length) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue