mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.10`: - [[EDR workflows] Osquery serverless tests (#163795)](https://github.com/elastic/kibana/pull/163795) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Tomasz Ciecierski","email":"tomasz.ciecierski@elastic.co"},"sourceCommit":{"committedDate":"2023-08-23T09:53:14Z","message":"[EDR workflows] Osquery serverless tests (#163795)","sha":"054cdbaf1e030f887953681abaa72dccac633480","branchLabelMapping":{"^v8.11.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["chore","release_note:skip","Team:Defend Workflows","Feature:Osquery","v8.10.0","v8.11.0"],"number":163795,"url":"https://github.com/elastic/kibana/pull/163795","mergeCommit":{"message":"[EDR workflows] Osquery serverless tests (#163795)","sha":"054cdbaf1e030f887953681abaa72dccac633480"}},"sourceBranch":"main","suggestedTargetBranches":["8.10"],"targetPullRequestStates":[{"branch":"8.10","label":"v8.10.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.11.0","labelRegex":"^v8.11.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/163795","number":163795,"mergeCommit":{"message":"[EDR workflows] Osquery serverless tests (#163795)","sha":"054cdbaf1e030f887953681abaa72dccac633480"}}]}] BACKPORT--> Co-authored-by: Tomasz Ciecierski <tomasz.ciecierski@elastic.co>
This commit is contained in:
parent
5cefc399aa
commit
79136c28dc
66 changed files with 1367 additions and 1385 deletions
|
@ -32,6 +32,7 @@ disabled:
|
|||
- x-pack/plugins/observability_onboarding/e2e/ftr_config_runner.ts
|
||||
- x-pack/plugins/observability_onboarding/e2e/ftr_config.ts
|
||||
- x-pack/test/osquery_cypress/cli_config.ts
|
||||
- x-pack/test/osquery_cypress/serverless_cli_config.ts
|
||||
- x-pack/test/osquery_cypress/config.ts
|
||||
- x-pack/test/osquery_cypress/visual_config.ts
|
||||
- x-pack/test/security_solution_cypress/cli_config.ts
|
||||
|
|
|
@ -22,3 +22,17 @@ steps:
|
|||
soft_fail: true
|
||||
artifact_paths:
|
||||
- "target/kibana-osquery/**/*"
|
||||
|
||||
- command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh
|
||||
label: 'Serverless Osquery Cypress Tests'
|
||||
agents:
|
||||
queue: n2-4-spot
|
||||
depends_on: build
|
||||
timeout_in_minutes: 50
|
||||
parallelism: 6
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: '*'
|
||||
limit: 1
|
||||
artifact_paths:
|
||||
- "target/kibana-osquery/**/*"
|
||||
|
|
|
@ -10,6 +10,7 @@ import { execSync } from 'child_process';
|
|||
import fs from 'fs';
|
||||
import prConfigs from '../../../pull_requests.json';
|
||||
import { areChangesSkippable, doAnyChangesMatch } from '#pipeline-utils';
|
||||
|
||||
const prConfig = prConfigs.jobs.find((job) => job.pipelineSlug === 'kibana-pull-request');
|
||||
|
||||
if (!prConfig) {
|
||||
|
|
15
.buildkite/scripts/steps/functional/security_serverless_osquery.sh
Executable file
15
.buildkite/scripts/steps/functional/security_serverless_osquery.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/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-serverless
|
||||
|
||||
echo "--- Security Osquery Serverless Cypress"
|
||||
|
||||
yarn --cwd x-pack/plugins/osquery cypress:serverless:run
|
|
@ -7,6 +7,19 @@
|
|||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
|
||||
import path from 'path';
|
||||
import { safeLoad as loadYaml } from 'js-yaml';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
import type { YamlRoleDefinitions } from '../../test_serverless/shared/lib';
|
||||
// eslint-disable-next-line @kbn/imports/no_boundary_crossing
|
||||
import { setupUserDataLoader } from '../../test_serverless/functional/test_suites/security/cypress/support/setup_data_loader_tasks';
|
||||
const ROLES_YAML_FILE_PATH = path.join(
|
||||
`${__dirname}/cypress/support`,
|
||||
'project_controller_osquery_roles.yml'
|
||||
);
|
||||
const roleDefinitions = loadYaml(readFileSync(ROLES_YAML_FILE_PATH, 'utf8')) as YamlRoleDefinitions;
|
||||
|
||||
export default defineCypressConfig({
|
||||
defaultCommandTimeout: 60000,
|
||||
execTimeout: 120000,
|
||||
|
@ -29,6 +42,9 @@ export default defineCypressConfig({
|
|||
'cypress-react-selector': {
|
||||
root: '#osquery-app',
|
||||
},
|
||||
grepFilterSpecs: true,
|
||||
grepTags: '@ess',
|
||||
grepOmitFiltered: true,
|
||||
},
|
||||
|
||||
e2e: {
|
||||
|
@ -37,5 +53,10 @@ export default defineCypressConfig({
|
|||
experimentalRunAllSpecs: true,
|
||||
experimentalMemoryManagement: true,
|
||||
numTestsKeptInMemory: 3,
|
||||
setupNodeEvents(on, config) {
|
||||
setupUserDataLoader(on, config, { roleDefinitions, additionalRoleName: 'viewer' });
|
||||
|
||||
return config;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import {
|
||||
cleanupPack,
|
||||
cleanupAgentPolicy,
|
||||
|
@ -28,11 +29,9 @@ import {
|
|||
interceptAgentPolicyId,
|
||||
policyContainsIntegration,
|
||||
} from '../../tasks/integrations';
|
||||
|
||||
import { login } from '../../tasks/login';
|
||||
import { findAndClickButton, findFormFieldByRowsLabelAndType } from '../../tasks/live_query';
|
||||
|
||||
describe('ALL - Add Integration', () => {
|
||||
describe('ALL - Add Integration', { tags: [tag.ESS, tag.BROKEN_IN_SERVERLESS] }, () => {
|
||||
let savedQueryId: string;
|
||||
|
||||
before(() => {
|
||||
|
@ -42,7 +41,7 @@ describe('ALL - Add Integration', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
cy.login('elastic');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
@ -63,7 +62,7 @@ describe('ALL - Add Integration', () => {
|
|||
cy.get(`[url="${NAV_SEARCH_INPUT_OSQUERY_RESULTS.MANAGER}"]`).should('exist').click();
|
||||
});
|
||||
|
||||
describe('Add and upgrade integration', () => {
|
||||
describe('Add and upgrade integration', { tags: [tag.ESS] }, () => {
|
||||
const oldVersion = '0.7.4';
|
||||
const [integrationName, policyName] = generateRandomStringName(2);
|
||||
let policyId: string;
|
||||
|
@ -78,7 +77,7 @@ describe('ALL - Add Integration', () => {
|
|||
cleanupAgentPolicy(policyId);
|
||||
});
|
||||
|
||||
it('should add the old integration and be able to upgrade it', () => {
|
||||
it('should add the old integration and be able to upgrade it', { tags: tag.ESS }, () => {
|
||||
cy.visit(createOldOsqueryPath(oldVersion));
|
||||
addCustomIntegration(integrationName, policyName);
|
||||
policyContainsIntegration(integrationName, policyName);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { LIVE_QUERY_EDITOR } from '../../screens/live_query';
|
||||
import {
|
||||
cleanupCase,
|
||||
cleanupPack,
|
||||
|
@ -14,17 +15,18 @@ import {
|
|||
loadRule,
|
||||
packFixture,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
addToCase,
|
||||
checkActionItemsInResults,
|
||||
clickRuleName,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { generateRandomStringName, interceptCaseId } from '../../tasks/integrations';
|
||||
|
||||
describe('Alert Event Details - Cases', () => {
|
||||
import { tag } from '../../tags';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
describe('Alert Event Details - Cases', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
let packId: string;
|
||||
|
@ -44,9 +46,9 @@ describe('Alert Event Details - Cases', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
clickRuleName(ruleName);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
@ -72,10 +74,10 @@ describe('Alert Event Details - Cases', () => {
|
|||
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}`);
|
||||
});
|
||||
cy.contains(/^\d+ agen(t|ts) selected/);
|
||||
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(`${packName}{downArrow}{enter}`);
|
||||
submitQuery();
|
||||
cy.get('[aria-label="Add to Case"]').first().click();
|
||||
cy.getBySel('cases-table-add-case-filter-bar').click();
|
||||
|
@ -91,7 +93,8 @@ describe('Alert Event Details - Cases', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Case', () => {
|
||||
// verify why calling new action doesnt add to response actions list
|
||||
describe.skip('Case', () => {
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
|
@ -134,6 +137,7 @@ describe('Alert Event Details - Cases', () => {
|
|||
cases: true,
|
||||
timeline: true,
|
||||
});
|
||||
|
||||
addToCase(caseId);
|
||||
viewRecentCaseAndCheckResults();
|
||||
});
|
||||
|
|
|
@ -7,19 +7,21 @@
|
|||
|
||||
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,
|
||||
clickRuleName,
|
||||
inputQuery,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { closeModalIfVisible, closeToastIfVisible } from '../../tasks/integrations';
|
||||
import { RESULTS_TABLE, RESULTS_TABLE_BUTTON } from '../../screens/live_query';
|
||||
import { tag } from '../../tags';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
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' }, () => {
|
||||
describe('Alert Event Details', { browser: 'electron', tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
|
@ -36,9 +38,9 @@ describe('Alert Event Details', { browser: 'electron' }, () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
clickRuleName(ruleName);
|
||||
});
|
||||
|
||||
it('should be able to add investigation guides to response actions', () => {
|
||||
|
@ -98,7 +100,7 @@ describe('Alert Event Details', { browser: 'electron' }, () => {
|
|||
closeModalIfVisible();
|
||||
});
|
||||
|
||||
it('can visit discover from response action results', () => {
|
||||
it('can visit discover from response action results', { tags: [tag.ESS] }, () => {
|
||||
const discoverRegex = new RegExp(`action_id: ${UUID_REGEX}`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
|
@ -124,7 +126,7 @@ describe('Alert Event Details', { browser: 'electron' }, () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('can visit lens from response action results', () => {
|
||||
it('can visit lens from response action results', { tags: [tag.ESS] }, () => {
|
||||
const lensRegex = new RegExp(`Action ${UUID_REGEX} results`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
|
@ -158,7 +160,7 @@ describe('Alert Event Details', { browser: 'electron' }, () => {
|
|||
cy.getBySel('breadcrumbs').contains(lensRegex);
|
||||
});
|
||||
|
||||
it('can add to timeline from response action results', () => {
|
||||
it('can add to timeline from response action results', { tags: [tag.ESS] }, () => {
|
||||
const timelineRegex = new RegExp(`Added ${UUID_REGEX} to timeline`);
|
||||
const filterRegex = new RegExp(`action_id: "${UUID_REGEX}"`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
|
|
|
@ -5,16 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import { cleanupRule, loadRule } from '../../tasks/api_fixtures';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
clickRuleName,
|
||||
inputQuery,
|
||||
loadRuleAlerts,
|
||||
submitQuery,
|
||||
takeOsqueryActionWithParams,
|
||||
} from '../../tasks/live_query';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('Alert Event Details - dynamic params', () => {
|
||||
describe('Alert Event Details - dynamic params', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
|
@ -31,9 +33,9 @@ describe('Alert Event Details - dynamic params', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
clickRuleName(ruleName);
|
||||
});
|
||||
|
||||
it('should substitute parameters in investigation guide', () => {
|
||||
|
|
|
@ -19,170 +19,180 @@ import {
|
|||
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 {
|
||||
checkActionItemsInResults,
|
||||
clickRuleName,
|
||||
inputQuery,
|
||||
typeInECSFieldInput,
|
||||
} from '../../tasks/live_query';
|
||||
import { closeDateTabIfVisible, closeToastIfVisible } from '../../tasks/integrations';
|
||||
import { tag } from '../../tags';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
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();
|
||||
describe(
|
||||
'Alert Event Details - Response Actions Form',
|
||||
{ browser: 'electron', tags: [tag.ESS, tag.SERVERLESS] },
|
||||
() => {
|
||||
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;
|
||||
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;
|
||||
});
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
});
|
||||
loadPack(multiQueryPackData).then((data) => {
|
||||
multiQueryPackId = data.saved_object_id;
|
||||
multiQueryPackName = data.name;
|
||||
afterEach(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupPack(multiQueryPackId);
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
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(() => {
|
||||
it('adds response actions with osquery with proper validation and form values', () => {
|
||||
cy.visit('/app/security/rules');
|
||||
clickRuleName(ruleName);
|
||||
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');
|
||||
})
|
||||
.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('comboBoxInput').type(`${packName}{downArrow}{enter}`);
|
||||
});
|
||||
|
||||
cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
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(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('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.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.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('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);
|
||||
});
|
||||
});
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import {
|
||||
addLiveQueryToCase,
|
||||
checkActionItemsInResults,
|
||||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { loadLiveQuery, loadCase, cleanupCase } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('Add to Cases', () => {
|
||||
let liveQueryId: string;
|
||||
let liveQueryQuery: string;
|
||||
|
||||
before(() => {
|
||||
loadLiveQuery({
|
||||
agent_all: true,
|
||||
|
@ -28,16 +28,15 @@ describe('Add to Cases', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('observability', () => {
|
||||
describe('observability', { tags: [tag.ESS] }, () => {
|
||||
let caseId: string;
|
||||
let caseTitle: string;
|
||||
|
||||
before(() => {
|
||||
loadCase('observability').then((caseInfo) => {
|
||||
caseId = caseInfo.id;
|
||||
caseTitle = caseInfo.title;
|
||||
});
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
|
@ -60,7 +59,7 @@ describe('Add to Cases', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('security', () => {
|
||||
describe('security', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let caseId: string;
|
||||
let caseTitle: string;
|
||||
|
||||
|
@ -69,7 +68,7 @@ describe('Add to Cases', () => {
|
|||
caseId = caseInfo.id;
|
||||
caseTitle = caseInfo.title;
|
||||
});
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
|
@ -15,10 +15,15 @@ import {
|
|||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { loadSpace, loadPack, cleanupPack, cleanupSpace } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
const testSpaces = [
|
||||
{ name: 'default', tags: [tag.ESS, tag.SERVERLESS] },
|
||||
{ name: 'custom-spaces', tags: [tag.ESS] },
|
||||
];
|
||||
describe('ALL - Custom space', () => {
|
||||
['default', 'custom-space'].forEach((spaceName) => {
|
||||
describe(`[${spaceName}]`, () => {
|
||||
testSpaces.forEach((testSpace) => {
|
||||
describe(`[${testSpace.name}]`, { tags: testSpace.tags }, () => {
|
||||
let packName: string;
|
||||
let packId: string;
|
||||
let spaceId: string;
|
||||
|
@ -26,7 +31,7 @@ describe('ALL - Custom space', () => {
|
|||
before(() => {
|
||||
cy.wrap(
|
||||
new Promise<string>((resolve) => {
|
||||
if (spaceName !== 'default') {
|
||||
if (testSpace.name !== 'default') {
|
||||
loadSpace().then((space) => {
|
||||
spaceId = space.id;
|
||||
resolve(spaceId);
|
||||
|
@ -56,18 +61,18 @@ describe('ALL - Custom space', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo(`/s/${spaceId}/app/osquery`);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId, spaceId);
|
||||
if (spaceName !== 'default') {
|
||||
if (testSpace.name !== 'default') {
|
||||
cleanupSpace(spaceId);
|
||||
}
|
||||
});
|
||||
|
||||
it('Discover should be opened in new tab in results table', () => {
|
||||
it('Discover should be opened in new tab in results table', { tags: [tag.ESS] }, () => {
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
inputQuery('select * from uptime;');
|
||||
|
@ -85,7 +90,6 @@ describe('ALL - Custom space', () => {
|
|||
.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.queryselect * from uptime');
|
||||
});
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import { getAdvancedButton } from '../../screens/integrations';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkResults,
|
||||
|
@ -17,10 +17,11 @@ import {
|
|||
typeInECSFieldInput,
|
||||
typeInOsqueryFieldInput,
|
||||
} from '../../tasks/live_query';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('EcsMapping', () => {
|
||||
describe('EcsMapping', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
});
|
||||
|
||||
it('should properly show static values in form and results', () => {
|
||||
|
@ -58,14 +59,17 @@ describe('EcsMapping', () => {
|
|||
cy.getBySel('savedQuerySelect').within(() => {
|
||||
cy.getBySel('comboBoxInput').type('processes_elastic{downArrow}{enter}');
|
||||
});
|
||||
cy.react('EuiAccordionClass', {
|
||||
props: { buttonContent: 'Advanced', forceState: 'open' },
|
||||
}).should('exist');
|
||||
cy.getBySel('advanced-accordion-content').within(() => {
|
||||
cy.contains('Advanced').click();
|
||||
});
|
||||
cy.react('EuiAccordionClass', {
|
||||
props: { buttonContent: 'Advanced', forceState: 'closed' },
|
||||
}).should('exist');
|
||||
|
||||
cy.contains('Use the fields below to map results from this query to ECS fields.').should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Advanced').click();
|
||||
cy.contains('Use the fields below to map results from this query to ECS fields.').should(
|
||||
'not.be.visible'
|
||||
);
|
||||
cy.contains('Advanced').click();
|
||||
cy.contains('Use the fields below to map results from this query to ECS fields.').should(
|
||||
'be.visible'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { loadSavedQuery, cleanupSavedQuery } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Edit saved query', () => {
|
||||
describe('ALL - Edit saved query', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let savedQueryName: string;
|
||||
let savedQueryId: string;
|
||||
|
||||
|
@ -21,7 +22,7 @@ describe('ALL - Edit saved query', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery/saved_queries');
|
||||
});
|
||||
|
||||
|
|
|
@ -5,91 +5,26 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
addToCase,
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
inputQuery,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
typeInECSFieldInput,
|
||||
typeInOsqueryFieldInput,
|
||||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import {
|
||||
LIVE_QUERY_EDITOR,
|
||||
RESULTS_TABLE,
|
||||
RESULTS_TABLE_BUTTON,
|
||||
RESULTS_TABLE_CELL_WRRAPER,
|
||||
} from '../../screens/live_query';
|
||||
import { LIVE_QUERY_EDITOR } from '../../screens/live_query';
|
||||
import { getAdvancedButton } from '../../screens/integrations';
|
||||
import {
|
||||
loadPack,
|
||||
loadSavedQuery,
|
||||
cleanupPack,
|
||||
cleanupCase,
|
||||
cleanupSavedQuery,
|
||||
loadCase,
|
||||
} from '../../tasks/api_fixtures';
|
||||
|
||||
describe('ALL - Live Query', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
let savedQueryId: string;
|
||||
let savedQueryName: string;
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
queries: {
|
||||
system_memory_linux_elastic: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
platform: 'linux',
|
||||
query: 'SELECT * FROM memory_info;',
|
||||
},
|
||||
system_info_elastic: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
platform: 'linux,windows,darwin',
|
||||
query: 'SELECT * FROM system_info;',
|
||||
},
|
||||
failingQuery: {
|
||||
ecs_mapping: {},
|
||||
interval: 10,
|
||||
query: 'select opera_extensions.* from users join opera_extensions using (uid);',
|
||||
},
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
loadSavedQuery({
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
ecs_mapping: {},
|
||||
}).then((savedQuery) => {
|
||||
savedQueryId = savedQuery.saved_object_id;
|
||||
savedQueryName = savedQuery.name;
|
||||
});
|
||||
loadCase('securitySolution').then((caseInfo) => {
|
||||
caseId = caseInfo.id;
|
||||
});
|
||||
});
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Live Query', { tags: [tag.SERVERLESS, tag.ESS] }, () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
cleanupCase(caseId);
|
||||
});
|
||||
|
||||
it('should validate the form', () => {
|
||||
cy.contains('New live query').click();
|
||||
submitQuery();
|
||||
|
@ -117,109 +52,6 @@ describe('ALL - Live Query', () => {
|
|||
cy.url().should('include', 'app/fleet/agents/');
|
||||
});
|
||||
|
||||
it('should run query and enable ecs mapping', () => {
|
||||
const cmd = Cypress.platform === 'darwin' ? '{meta}{enter}' : '{ctrl}{enter}';
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
inputQuery('select * from uptime;');
|
||||
cy.wait(500);
|
||||
// checking submit by clicking cmd+enter
|
||||
inputQuery(cmd);
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'osquery.days.number', index: 1 },
|
||||
}).should('exist');
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'osquery.hours.number', index: 2 },
|
||||
}).should('exist');
|
||||
|
||||
getAdvancedButton().click();
|
||||
typeInECSFieldInput('message{downArrow}{enter}');
|
||||
typeInOsqueryFieldInput('days{downArrow}{enter}');
|
||||
submitQuery();
|
||||
|
||||
checkResults();
|
||||
cy.getBySel(RESULTS_TABLE).within(() => {
|
||||
cy.getBySel(RESULTS_TABLE_BUTTON).should('exist');
|
||||
});
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'message', index: 1 },
|
||||
}).should('exist');
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'osquery.days.number', index: 2 },
|
||||
})
|
||||
.react('EuiIconTip', { props: { type: 'indexMapping' } })
|
||||
.should('exist');
|
||||
});
|
||||
|
||||
it('should run customized saved query', () => {
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
cy.react('SavedQueriesDropdown').type(`${savedQueryName}{downArrow}{enter}`);
|
||||
inputQuery('{selectall}{backspace}select * from users;');
|
||||
cy.wait(1000);
|
||||
submitQuery();
|
||||
checkResults();
|
||||
navigateTo('/app/osquery');
|
||||
cy.react('EuiButtonIcon', { props: { iconType: 'play' } })
|
||||
.eq(0)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get(LIVE_QUERY_EDITOR).contains('select * from users;');
|
||||
});
|
||||
|
||||
it('should open query details by clicking the details icon', () => {
|
||||
cy.react('EuiButtonIcon', { props: { iconType: 'visTable' } })
|
||||
.first()
|
||||
.click();
|
||||
cy.contains('Live query details');
|
||||
cy.contains('select * from users;');
|
||||
});
|
||||
|
||||
it('should run live pack', () => {
|
||||
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(`${packName}{downArrow}{enter}`);
|
||||
cy.contains('This table contains 3 rows.');
|
||||
cy.contains('system_memory_linux_elastic');
|
||||
cy.contains('system_info_elastic');
|
||||
cy.contains('failingQuery');
|
||||
selectAllAgents();
|
||||
submitQuery();
|
||||
cy.getBySel('live-query-loading').should('exist');
|
||||
cy.getBySel('live-query-loading', { timeout: 10000 }).should('not.exist');
|
||||
cy.getBySel('toggleIcon-system_memory_linux_elastic').click();
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
cy.contains('Status').click();
|
||||
cy.getBySel('tableHeaderCell_status_0').should('exist');
|
||||
cy.getBySel('tableHeaderCell_fields.agent_id[0]_1').should('exist');
|
||||
cy.getBySel('tableHeaderCell__source.action_response.osquery.count_2').should('exist');
|
||||
cy.getBySel('tableHeaderCell_fields.error[0]_3').should('exist');
|
||||
|
||||
cy.getBySel('toggleIcon-system_memory_linux_elastic').click();
|
||||
cy.getBySel('toggleIcon-failingQuery').click();
|
||||
cy.contains('Status').click();
|
||||
cy.contains('query failed, code: 1, message: no such table: opera_extensions');
|
||||
cy.getBySel('toggleIcon-failingQuery').click();
|
||||
cy.getBySel('toggleIcon-system_memory_linux_elastic').click();
|
||||
addToCase(caseId);
|
||||
viewRecentCaseAndCheckResults();
|
||||
});
|
||||
|
||||
it('should run multiline query', () => {
|
||||
const multilineQuery =
|
||||
'select u.username, {shift+enter}' +
|
||||
|
@ -255,6 +87,6 @@ describe('ALL - Live Query', () => {
|
|||
|
||||
inputQuery('{selectall}{backspace}{selectall}{backspace}');
|
||||
// not sure if this is how it used to work when I implemented the functionality, but let's leave it like this for now
|
||||
cy.get(LIVE_QUERY_EDITOR).invoke('height').should('be.gt', 200).and('be.lt', 350);
|
||||
cy.get(LIVE_QUERY_EDITOR).invoke('height').should('be.gt', 200).and('be.lt', 380);
|
||||
});
|
||||
});
|
||||
|
|
104
x-pack/plugins/osquery/cypress/e2e/all/live_query_packs.cy.ts
Normal file
104
x-pack/plugins/osquery/cypress/e2e/all/live_query_packs.cy.ts
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
addToCase,
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { LIVE_QUERY_EDITOR } from '../../screens/live_query';
|
||||
import { loadPack, cleanupPack, cleanupCase, loadCase } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Live Query Packs', { tags: [tag.SERVERLESS, tag.ESS] }, () => {
|
||||
let packName: string;
|
||||
let packId: string;
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
queries: {
|
||||
system_memory_linux_elastic: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
platform: 'linux',
|
||||
query: 'SELECT * FROM memory_info;',
|
||||
},
|
||||
system_info_elastic: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
platform: 'linux,windows,darwin',
|
||||
query: 'SELECT * FROM system_info;',
|
||||
},
|
||||
failingQuery: {
|
||||
ecs_mapping: {},
|
||||
interval: 10,
|
||||
query: 'select opera_extensions.* from users join opera_extensions using (uid);',
|
||||
},
|
||||
},
|
||||
}).then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
|
||||
loadCase('securitySolution').then((caseInfo) => {
|
||||
caseId = caseInfo.id;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupCase(caseId);
|
||||
});
|
||||
|
||||
it('should run live pack', () => {
|
||||
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(`${packName}{downArrow}{enter}`);
|
||||
cy.contains('This table contains 3 rows.');
|
||||
cy.contains('system_memory_linux_elastic');
|
||||
cy.contains('system_info_elastic');
|
||||
cy.contains('failingQuery');
|
||||
selectAllAgents();
|
||||
submitQuery();
|
||||
cy.getBySel('live-query-loading').should('exist');
|
||||
cy.getBySel('live-query-loading', { timeout: 10000 }).should('not.exist');
|
||||
cy.getBySel('toggleIcon-system_memory_linux_elastic').click();
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
cy.contains('Status').click();
|
||||
cy.getBySel('tableHeaderCell_status_0').should('exist');
|
||||
cy.getBySel('tableHeaderCell_fields.agent_id[0]_1').should('exist');
|
||||
cy.getBySel('tableHeaderCell__source.action_response.osquery.count_2').should('exist');
|
||||
cy.getBySel('tableHeaderCell_fields.error[0]_3').should('exist');
|
||||
|
||||
cy.getBySel('toggleIcon-system_memory_linux_elastic').click();
|
||||
cy.getBySel('toggleIcon-failingQuery').click();
|
||||
cy.contains('Status').click();
|
||||
cy.contains('query failed, code: 1, message: no such table: opera_extensions');
|
||||
cy.getBySel('toggleIcon-failingQuery').click();
|
||||
cy.getBySel('toggleIcon-system_memory_linux_elastic').click();
|
||||
addToCase(caseId);
|
||||
viewRecentCaseAndCheckResults();
|
||||
});
|
||||
});
|
118
x-pack/plugins/osquery/cypress/e2e/all/live_query_run.cy.ts
Normal file
118
x-pack/plugins/osquery/cypress/e2e/all/live_query_run.cy.ts
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
inputQuery,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
typeInECSFieldInput,
|
||||
typeInOsqueryFieldInput,
|
||||
} from '../../tasks/live_query';
|
||||
import {
|
||||
LIVE_QUERY_EDITOR,
|
||||
RESULTS_TABLE,
|
||||
RESULTS_TABLE_BUTTON,
|
||||
RESULTS_TABLE_CELL_WRRAPER,
|
||||
} from '../../screens/live_query';
|
||||
import { getAdvancedButton } from '../../screens/integrations';
|
||||
import { loadSavedQuery, cleanupSavedQuery } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Live Query run custom and saved', { tags: [tag.ESS] }, () => {
|
||||
let savedQueryId: string;
|
||||
let savedQueryName: string;
|
||||
|
||||
before(() => {
|
||||
loadSavedQuery({
|
||||
interval: '3600',
|
||||
query: 'select * from uptime;',
|
||||
ecs_mapping: {},
|
||||
}).then((savedQuery) => {
|
||||
savedQueryId = savedQuery.saved_object_id;
|
||||
savedQueryName = savedQuery.name;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
});
|
||||
|
||||
it('should run query and enable ecs mapping', () => {
|
||||
const cmd = Cypress.platform === 'darwin' ? '{meta}{enter}' : '{ctrl}{enter}';
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
inputQuery('select * from uptime;');
|
||||
cy.wait(500);
|
||||
// checking submit by clicking cmd+enter
|
||||
inputQuery(cmd);
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'osquery.days.number', index: 1 },
|
||||
}).should('exist');
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'osquery.hours.number', index: 2 },
|
||||
}).should('exist');
|
||||
|
||||
getAdvancedButton().click();
|
||||
typeInECSFieldInput('message{downArrow}{enter}');
|
||||
typeInOsqueryFieldInput('days{downArrow}{enter}');
|
||||
submitQuery();
|
||||
|
||||
checkResults();
|
||||
cy.getBySel(RESULTS_TABLE).within(() => {
|
||||
cy.getBySel(RESULTS_TABLE_BUTTON).should('exist');
|
||||
});
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'message', index: 1 },
|
||||
}).should('exist');
|
||||
cy.react(RESULTS_TABLE_CELL_WRRAPER, {
|
||||
props: { id: 'osquery.days.number', index: 2 },
|
||||
})
|
||||
.react('EuiIconTip', { props: { type: 'indexMapping' } })
|
||||
.should('exist');
|
||||
});
|
||||
|
||||
it('should run customized saved query', () => {
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
cy.react('SavedQueriesDropdown').type(`${savedQueryName}{downArrow}{enter}`);
|
||||
inputQuery('{selectall}{backspace}select * from users;');
|
||||
cy.wait(1000);
|
||||
submitQuery();
|
||||
checkResults();
|
||||
navigateTo('/app/osquery');
|
||||
cy.react('EuiButtonIcon', { props: { iconType: 'play' } })
|
||||
.eq(0)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get(LIVE_QUERY_EDITOR).contains('select * from users;');
|
||||
});
|
||||
|
||||
it('should open query details by clicking the details icon', () => {
|
||||
cy.react('EuiButtonIcon', { props: { iconType: 'visTable' } })
|
||||
.first()
|
||||
.click();
|
||||
cy.contains('Live query details');
|
||||
cy.contains('select * from users;');
|
||||
});
|
||||
});
|
|
@ -5,13 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { checkResults, inputQuery, submitQuery } from '../../tasks/live_query';
|
||||
import { loadSavedQuery, cleanupSavedQuery } from '../../tasks/api_fixtures';
|
||||
import { triggerLoadData } from '../../tasks/inventory';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Inventory', () => {
|
||||
describe('ALL - Inventory', { tags: [tag.ESS] }, () => {
|
||||
let savedQueryName: string;
|
||||
let savedQueryId: string;
|
||||
|
||||
|
@ -23,7 +24,7 @@ describe('ALL - Inventory', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { recurse } from 'cypress-recurse';
|
||||
import type { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { tag } from '../../tags';
|
||||
import { API_VERSIONS } from '../../../common/constants';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
|
@ -15,7 +16,6 @@ import {
|
|||
findFormFieldByRowsLabelAndType,
|
||||
inputQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { activatePack, deactivatePack, preparePack } from '../../tasks/packs';
|
||||
import {
|
||||
closeModalIfVisible,
|
||||
|
@ -27,6 +27,7 @@ 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';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('Packs - Create and Edit', () => {
|
||||
let savedQueryId: string;
|
||||
|
@ -86,7 +87,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
|
@ -97,7 +98,7 @@ describe('Packs - Create and Edit', () => {
|
|||
cleanupSavedQuery(multipleMappingsSavedQueryId);
|
||||
});
|
||||
|
||||
describe('Check if result type is correct', () => {
|
||||
describe('Check if result type is correct', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let resultTypePackId: string;
|
||||
|
||||
before(() => {
|
||||
|
@ -221,7 +222,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Check if pack is created', () => {
|
||||
describe('Check if pack is created', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
const packName = 'Pack-name' + generateRandomStringName(1)[0];
|
||||
let packId: string;
|
||||
|
||||
|
@ -261,7 +262,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('to click the edit button and edit pack', () => {
|
||||
describe('to click the edit button and edit pack', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
const newQueryName = 'new-query-name' + generateRandomStringName(1)[0];
|
||||
|
||||
let packId: string;
|
||||
|
@ -314,7 +315,57 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('should trigger validation when saved query is being chosen', () => {
|
||||
describe(
|
||||
'should trigger validation when saved query is being chosen',
|
||||
{ tags: [tag.ESS, tag.SERVERLESS] },
|
||||
() => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
loadPack({
|
||||
policy_ids: [response.body.items[0].policy_id],
|
||||
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', { tags: [tag.ESS] }, () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
|
@ -329,49 +380,11 @@ describe('Packs - Create and Edit', () => {
|
|||
loadPack({
|
||||
policy_ids: [response.body.items[0].policy_id],
|
||||
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(() => {
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
loadPack({
|
||||
policy_ids: [response.body.items[0].policy_id],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
[savedQueryName]: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
@ -461,7 +474,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('deactivate and activate pack', () => {
|
||||
describe('deactivate and activate pack', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
|
@ -497,7 +510,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('should verify that packs are triggered', () => {
|
||||
describe('should verify that packs are triggered', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
|
@ -564,7 +577,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('delete all queries in the pack', () => {
|
||||
describe('delete all queries in the pack', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
|
@ -610,74 +623,82 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('enable changing saved queries and ecs_mappings', () => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
describe(
|
||||
'enable changing saved queries and ecs_mappings',
|
||||
{ tags: [tag.ESS, tag.SERVERLESS] },
|
||||
() => {
|
||||
let packId: string;
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
loadPack({
|
||||
policy_ids: [response.body.items[0].policy_id],
|
||||
queries: {
|
||||
[savedQueryName]: { ecs_mapping: {}, interval: 3600, query: 'select * from uptime;' },
|
||||
},
|
||||
})
|
||||
)
|
||||
.then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
before(() => {
|
||||
request<{ items: PackagePolicy[] }>({
|
||||
url: '/internal/osquery/fleet_wrapper/package_policies',
|
||||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.internal.v1,
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
loadPack({
|
||||
policy_ids: [response.body.items[0].policy_id],
|
||||
queries: {
|
||||
[savedQueryName]: {
|
||||
ecs_mapping: {},
|
||||
interval: 3600,
|
||||
query: 'select * from uptime;',
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then((pack) => {
|
||||
packId = pack.saved_object_id;
|
||||
packName = pack.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(/^Edit$/).click();
|
||||
it('', () => {
|
||||
preparePack(packName);
|
||||
cy.contains(/^Edit$/).click();
|
||||
|
||||
findAndClickButton('Add query');
|
||||
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(`${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(`${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);
|
||||
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');
|
||||
});
|
||||
});
|
||||
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', () => {
|
||||
describe('to click delete button', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let packName: string;
|
||||
|
||||
before(() => {
|
||||
|
@ -700,7 +721,7 @@ describe('Packs - Create and Edit', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('', () => {
|
||||
it('', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
deleteAndConfirm('pack');
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { find } from 'lodash';
|
||||
import type { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { tag } from '../../tags';
|
||||
import { API_VERSIONS } from '../../../common/constants';
|
||||
import { FLEET_AGENT_POLICIES, navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
|
@ -18,7 +19,6 @@ import {
|
|||
selectAllAgents,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { activatePack, cleanupAllPrebuiltPacks, deactivatePack } from '../../tasks/packs';
|
||||
import {
|
||||
addIntegration,
|
||||
|
@ -32,65 +32,70 @@ 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';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Packs', () => {
|
||||
describe('ALL - Packs', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
const integration = 'Osquery Manager';
|
||||
|
||||
describe('Validate that agent policy is getting removed from pack if we remove agent policy', () => {
|
||||
describe(
|
||||
'Validate that agent policy is getting removed from pack if we remove agent policy',
|
||||
{ tags: [tag.ESS] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
cy.login('elastic');
|
||||
});
|
||||
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', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
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);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery/packs');
|
||||
});
|
||||
|
||||
|
@ -156,7 +161,6 @@ describe('ALL - Packs', () => {
|
|||
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({
|
||||
|
@ -170,9 +174,9 @@ describe('ALL - Packs', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Global packs', () => {
|
||||
describe('Global packs', { tags: [tag.ESS] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
cy.login('elastic');
|
||||
navigateTo('/app/osquery/packs');
|
||||
});
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import { preparePack } from '../../tasks/packs';
|
||||
import {
|
||||
addToCase,
|
||||
|
@ -18,11 +19,11 @@ import {
|
|||
viewRecentCaseAndCheckResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { getSavedQueriesComplexTest } from '../../tasks/saved_queries';
|
||||
import { loadCase, cleanupCase, loadPack, cleanupPack } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Saved queries', () => {
|
||||
describe('ALL - Saved queries', { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let caseId: string;
|
||||
|
||||
before(() => {
|
||||
|
@ -32,7 +33,7 @@ describe('ALL - Saved queries', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { tag } from '../../tags';
|
||||
import { takeOsqueryActionWithParams } from '../../tasks/live_query';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('ALL - Timelines', () => {
|
||||
describe('ALL - Timelines', { tags: [tag.ESS] }, () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
});
|
||||
|
||||
it('should substitute osquery parameter on non-alert event take action', () => {
|
||||
|
|
|
@ -1,25 +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 { ROLE, login } from '../../tasks/login';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { checkResults, inputQuery, selectAllAgents, submitQuery } from '../../tasks/live_query';
|
||||
|
||||
describe('Admin', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.admin);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
it('should be able to run live query with BASE All permissions', () => {
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
inputQuery('select * from uptime;');
|
||||
submitQuery();
|
||||
checkResults();
|
||||
});
|
||||
});
|
|
@ -5,103 +5,39 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import {
|
||||
checkResults,
|
||||
findAndClickButton,
|
||||
findFormFieldByRowsLabelAndType,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { closeModalIfVisible, closeToastIfVisible } from '../../tasks/integrations';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import { loadPack, loadRule, cleanupRule, cleanupPack } from '../../tasks/api_fixtures';
|
||||
import { preparePack } from '../../tasks/packs';
|
||||
import { DEFAULT_POLICY } from '../../screens/fleet';
|
||||
import { tag } from '../../tags';
|
||||
import { checkResults, clickRuleName, submitQuery } from '../../tasks/live_query';
|
||||
import { loadRule, cleanupRule } from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('Alert Test', () => {
|
||||
let packName: string;
|
||||
let packId: string;
|
||||
describe('Alert Test', { tags: [tag.ESS] }, () => {
|
||||
let ruleName: string;
|
||||
let ruleId: string;
|
||||
|
||||
before(() => {
|
||||
loadPack({
|
||||
description: '',
|
||||
enabled: true,
|
||||
queries: {
|
||||
packQuery: {
|
||||
interval: 10,
|
||||
query: 'select * from uptime;',
|
||||
ecs_mapping: {},
|
||||
},
|
||||
},
|
||||
}).then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.alert_test);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupPack(packId);
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
describe('alert_test role', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.alert_test);
|
||||
});
|
||||
|
||||
it('should not be able to run live query', () => {
|
||||
navigateTo('/app/osquery');
|
||||
preparePack(packName);
|
||||
findAndClickButton('Edit');
|
||||
cy.contains(`Edit ${packName}`);
|
||||
findFormFieldByRowsLabelAndType(
|
||||
'Scheduled agent policies (optional)',
|
||||
`${DEFAULT_POLICY} {downArrow}{enter}`
|
||||
);
|
||||
findAndClickButton('Update pack');
|
||||
closeModalIfVisible();
|
||||
cy.contains(`Successfully updated "${packName}" pack`);
|
||||
closeToastIfVisible();
|
||||
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
cy.wait(2000);
|
||||
cy.getBySel('ruleSwitch').should('have.attr', 'aria-checked', 'true');
|
||||
cy.getBySel('ruleSwitch').click();
|
||||
cy.getBySel('ruleSwitch').should('have.attr', 'aria-checked', 'false');
|
||||
cy.getBySel('ruleSwitch').click();
|
||||
cy.getBySel('ruleSwitch').should('have.attr', 'aria-checked', 'true');
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('osquery-action-item').click();
|
||||
|
||||
cy.contains('Run Osquery');
|
||||
cy.contains('Permission denied');
|
||||
ruleId = data.id;
|
||||
});
|
||||
});
|
||||
|
||||
describe('t1_analyst role', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.t1_analyst);
|
||||
cy.login(ServerlessRoleName.T1_ANALYST);
|
||||
|
||||
cy.visit(`/app/security/rules/id/${ruleId}/alerts`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.visit('/app/security/rules');
|
||||
clickRuleName(ruleName);
|
||||
cy.getBySel('expand-event').first().click({ force: true });
|
||||
|
||||
cy.wait(500);
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutInvestigationGuideButton').click();
|
||||
cy.contains('Get processes').click();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should be able to run rule investigation guide query', () => {
|
||||
submitQuery();
|
||||
checkResults();
|
||||
|
|
|
@ -1,73 +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 { ROLE, login } from '../../tasks/login';
|
||||
import { NAV_SEARCH_INPUT_OSQUERY_RESULTS } from '../../tasks/navigation';
|
||||
import { loadRule, cleanupRule } from '../../tasks/api_fixtures';
|
||||
|
||||
describe('None', () => {
|
||||
beforeEach(() => {
|
||||
login(ROLE.none);
|
||||
|
||||
cy.visit('/app/home');
|
||||
});
|
||||
|
||||
it('should not see osquery in global search', () => {
|
||||
cy.getBySel('nav-search-input').type('Osquery');
|
||||
cy.get(`[url="${NAV_SEARCH_INPUT_OSQUERY_RESULTS.MANAGEMENT}"]`).should('not.exist');
|
||||
cy.get(`[url="${NAV_SEARCH_INPUT_OSQUERY_RESULTS.LOGS}"]`).should('not.exist');
|
||||
cy.get(`[url="${NAV_SEARCH_INPUT_OSQUERY_RESULTS.MANAGER}"]`).should('not.exist');
|
||||
});
|
||||
|
||||
it('should get 403 forbidden response when trying to GET osquery', () => {
|
||||
cy.request({
|
||||
url: '/app/osquery/live_queries',
|
||||
failOnStatusCode: false,
|
||||
}).then((resp) => {
|
||||
expect(resp.status).to.eq(403);
|
||||
});
|
||||
cy.request({
|
||||
url: '/app/osquery/saved_queries',
|
||||
failOnStatusCode: false,
|
||||
}).then((resp) => {
|
||||
expect(resp.status).to.eq(403);
|
||||
});
|
||||
cy.request({
|
||||
url: '/app/osquery/packs',
|
||||
failOnStatusCode: false,
|
||||
}).then((resp) => {
|
||||
expect(resp.status).to.eq(403);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Detection Engine', () => {
|
||||
let ruleId: string;
|
||||
|
||||
before(() => {
|
||||
login(ROLE.soc_manager);
|
||||
loadRule(true).then((data) => {
|
||||
ruleId = data.id;
|
||||
});
|
||||
cy.visit(`/app/security/alerts`);
|
||||
cy.getBySel('expand-event').should('exist');
|
||||
login(ROLE.none);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
it('should not see osquery in alerts', () => {
|
||||
cy.visit(`/app/security/rules/id/${ruleId}/alerts`);
|
||||
cy.getBySel('expand-event').first().click();
|
||||
cy.getBySel('take-action-dropdown-btn').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseSectionHeader').click();
|
||||
cy.getBySel('securitySolutionDocumentDetailsFlyoutResponseButton').click();
|
||||
cy.contains('Permission denied').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { tag } from '../../tags';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
cleanupPack,
|
||||
|
@ -14,8 +14,9 @@ import {
|
|||
loadPack,
|
||||
loadSavedQuery,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe('Reader - only READ', () => {
|
||||
describe('Reader - only READ', { tags: [tag.ESS] }, () => {
|
||||
let savedQueryName: string;
|
||||
let savedQueryId: string;
|
||||
let packName: string;
|
||||
|
@ -37,7 +38,7 @@ describe('Reader - only READ', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.reader);
|
||||
cy.login(ServerlessRoleName.READER);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
|
|
@ -1,135 +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 { SAVED_QUERY_ID } from '../../../public/saved_queries/constants';
|
||||
import { ROLE, login } from '../../tasks/login';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { getSavedQueriesDropdown, LIVE_QUERY_EDITOR } from '../../screens/live_query';
|
||||
import {
|
||||
cleanupPack,
|
||||
cleanupSavedQuery,
|
||||
loadLiveQuery,
|
||||
loadPack,
|
||||
loadSavedQuery,
|
||||
} from '../../tasks/api_fixtures';
|
||||
|
||||
describe('T1 Analyst - READ + runSavedQueries ', () => {
|
||||
let savedQueryName: string;
|
||||
let savedQueryId: string;
|
||||
let packName: string;
|
||||
let packId: string;
|
||||
let liveQueryQuery: string;
|
||||
|
||||
before(() => {
|
||||
loadPack().then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadSavedQuery().then((data) => {
|
||||
savedQueryId = data.saved_object_id;
|
||||
savedQueryName = data.id;
|
||||
});
|
||||
loadLiveQuery().then((data) => {
|
||||
liveQueryQuery = data.queries?.[0].query;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.t1_analyst);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('should be able to run saved queries but not add new ones', () => {
|
||||
navigateTo('/app/osquery/saved_queries');
|
||||
cy.waitForReact(1000);
|
||||
cy.contains(savedQueryName);
|
||||
cy.contains('Add saved query').should('be.disabled');
|
||||
cy.react('PlayButtonComponent', {
|
||||
props: { savedQuery: { id: savedQueryName } },
|
||||
})
|
||||
.should('not.be.disabled')
|
||||
.click();
|
||||
selectAllAgents();
|
||||
cy.contains('select * from uptime;');
|
||||
submitQuery();
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: false,
|
||||
discover: false,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to play in live queries history', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
cy.waitForReact(1000);
|
||||
cy.contains('New live query').should('not.be.disabled');
|
||||
cy.contains(liveQueryQuery);
|
||||
cy.wait(1000);
|
||||
cy.react('EuiTableBody').first().react('CustomItemAction').first().click();
|
||||
cy.contains(savedQueryName);
|
||||
submitQuery();
|
||||
checkResults();
|
||||
});
|
||||
|
||||
it('should be able to use saved query in a new query', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
cy.waitForReact(1000);
|
||||
cy.contains('New live query').should('not.be.disabled').click();
|
||||
selectAllAgents();
|
||||
getSavedQueriesDropdown().type(`${savedQueryName}{downArrow} {enter}`);
|
||||
cy.contains('select * from uptime');
|
||||
submitQuery();
|
||||
checkResults();
|
||||
});
|
||||
|
||||
it('should not be able to add nor edit packs', () => {
|
||||
navigateTo('/app/osquery/packs');
|
||||
cy.waitForReact(1000);
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains('Add pack').should('be.disabled');
|
||||
cy.react('ActiveStateSwitchComponent', {
|
||||
props: { item: { name: packName } },
|
||||
})
|
||||
.find('button')
|
||||
.should('be.disabled');
|
||||
cy.contains(packName).click();
|
||||
cy.contains(`${packName} details`);
|
||||
cy.contains('Edit').should('be.disabled');
|
||||
// TODO: fix it
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: SAVED_QUERY_ID } },
|
||||
options: { timeout: 3000 },
|
||||
}).should('not.exist');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 1, item: { id: SAVED_QUERY_ID } },
|
||||
options: { timeout: 3000 },
|
||||
}).should('not.exist');
|
||||
});
|
||||
|
||||
it('should not be able to create new liveQuery from scratch', () => {
|
||||
navigateTo('/app/osquery');
|
||||
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
cy.get(LIVE_QUERY_EDITOR).should('not.exist');
|
||||
submitQuery();
|
||||
cy.contains('Query is a required field');
|
||||
});
|
||||
});
|
140
x-pack/plugins/osquery/cypress/e2e/roles/t1_and_t2_analyst.cy.ts
Normal file
140
x-pack/plugins/osquery/cypress/e2e/roles/t1_and_t2_analyst.cy.ts
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { SAVED_QUERY_ID } from '../../../public/saved_queries/constants';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkActionItemsInResults,
|
||||
checkResults,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
} from '../../tasks/live_query';
|
||||
import { getSavedQueriesDropdown, LIVE_QUERY_EDITOR } from '../../screens/live_query';
|
||||
import {
|
||||
cleanupPack,
|
||||
cleanupSavedQuery,
|
||||
loadLiveQuery,
|
||||
loadPack,
|
||||
loadSavedQuery,
|
||||
} from '../../tasks/api_fixtures';
|
||||
import type { ServerlessRoleName } from '../../support/roles';
|
||||
|
||||
describe(`T1 and T2 analysts`, { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
['t1_analyst', 't2_analyst'].forEach((role: string) => {
|
||||
describe(`${role}- READ + runSavedQueries `, { tags: [tag.ESS, tag.SERVERLESS] }, () => {
|
||||
let savedQueryName: string;
|
||||
let savedQueryId: string;
|
||||
let packName: string;
|
||||
let packId: string;
|
||||
let liveQueryQuery: string;
|
||||
|
||||
before(() => {
|
||||
loadPack().then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadSavedQuery().then((data) => {
|
||||
savedQueryId = data.saved_object_id;
|
||||
savedQueryName = data.id;
|
||||
});
|
||||
loadLiveQuery().then((data) => {
|
||||
liveQueryQuery = data.queries?.[0].query;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(role as ServerlessRoleName);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
it('should be able to run saved queries but not add new ones', () => {
|
||||
navigateTo('/app/osquery/saved_queries');
|
||||
cy.waitForReact(1000);
|
||||
cy.contains(savedQueryName);
|
||||
cy.contains('Add saved query').should('be.disabled');
|
||||
cy.react('PlayButtonComponent', {
|
||||
props: { savedQuery: { id: savedQueryName } },
|
||||
})
|
||||
.should('not.be.disabled')
|
||||
.click();
|
||||
selectAllAgents();
|
||||
cy.contains('select * from uptime;');
|
||||
submitQuery();
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: true,
|
||||
discover: true,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to play in live queries history', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
cy.waitForReact(1000);
|
||||
cy.contains('New live query').should('not.be.disabled');
|
||||
cy.contains(liveQueryQuery);
|
||||
cy.wait(1000);
|
||||
cy.react('EuiTableBody').first().react('CustomItemAction').first().click();
|
||||
cy.contains(savedQueryName);
|
||||
submitQuery();
|
||||
checkResults();
|
||||
});
|
||||
|
||||
it('should be able to use saved query in a new query', () => {
|
||||
navigateTo('/app/osquery/live_queries');
|
||||
cy.waitForReact(1000);
|
||||
cy.contains('New live query').should('not.be.disabled').click();
|
||||
selectAllAgents();
|
||||
getSavedQueriesDropdown().type(`${savedQueryName}{downArrow} {enter}`);
|
||||
cy.contains('select * from uptime');
|
||||
submitQuery();
|
||||
checkResults();
|
||||
});
|
||||
|
||||
it('should not be able to add nor edit packs', () => {
|
||||
navigateTo('/app/osquery/packs');
|
||||
cy.waitForReact(1000);
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains('Add pack').should('be.disabled');
|
||||
cy.react('ActiveStateSwitchComponent', {
|
||||
props: { item: { name: packName } },
|
||||
})
|
||||
.find('button')
|
||||
.should('be.disabled');
|
||||
cy.contains(packName).click();
|
||||
cy.contains(`${packName} details`);
|
||||
cy.contains('Edit').should('be.disabled');
|
||||
// TODO: fix it
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: SAVED_QUERY_ID } },
|
||||
options: { timeout: 3000 },
|
||||
}).should('not.exist');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 1, item: { id: SAVED_QUERY_ID } },
|
||||
options: { timeout: 3000 },
|
||||
}).should('not.exist');
|
||||
});
|
||||
|
||||
it('should not be able to create new liveQuery from scratch', () => {
|
||||
navigateTo('/app/osquery');
|
||||
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
cy.get(LIVE_QUERY_EDITOR).should('not.exist');
|
||||
submitQuery();
|
||||
cy.contains('Query is a required field');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,142 +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 { ROLE, login } from '../../tasks/login';
|
||||
import { navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
checkResults,
|
||||
selectAllAgents,
|
||||
submitQuery,
|
||||
inputQuery,
|
||||
typeInECSFieldInput,
|
||||
typeInOsqueryFieldInput,
|
||||
checkActionItemsInResults,
|
||||
} from '../../tasks/live_query';
|
||||
import { getSavedQueriesComplexTest } from '../../tasks/saved_queries';
|
||||
import { loadPack, loadSavedQuery, cleanupSavedQuery, cleanupPack } from '../../tasks/api_fixtures';
|
||||
|
||||
describe('T2 Analyst - READ + Write Live/Saved + runSavedQueries ', () => {
|
||||
const SAVED_QUERY_ID = 'Saved-Query-Id';
|
||||
|
||||
let savedQueryName: string;
|
||||
let savedQueryId: string;
|
||||
let packName: string;
|
||||
let packId: string;
|
||||
|
||||
before(() => {
|
||||
loadPack().then((data) => {
|
||||
packId = data.saved_object_id;
|
||||
packName = data.name;
|
||||
});
|
||||
loadSavedQuery().then((data) => {
|
||||
savedQueryId = data.saved_object_id;
|
||||
savedQueryName = data.id;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLE.t2_analyst);
|
||||
navigateTo('/app/osquery');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cleanupSavedQuery(savedQueryId);
|
||||
cleanupPack(packId);
|
||||
});
|
||||
|
||||
getSavedQueriesComplexTest();
|
||||
|
||||
it('should not be able to add nor edit packs', () => {
|
||||
navigateTo('/app/osquery/packs');
|
||||
cy.waitForReact(1000);
|
||||
cy.getBySel('tablePaginationPopoverButton').click();
|
||||
cy.getBySel('tablePagination-50-rows').click();
|
||||
cy.contains('Add pack').should('be.disabled');
|
||||
cy.react('ActiveStateSwitchComponent', {
|
||||
props: { item: { name: packName } },
|
||||
})
|
||||
.find('button')
|
||||
.should('be.disabled');
|
||||
cy.contains(packName).click();
|
||||
cy.contains(`${packName} details`);
|
||||
cy.contains('Edit').should('be.disabled');
|
||||
// TODO: fix
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 0, item: { id: SAVED_QUERY_ID } },
|
||||
options: { timeout: 3000 },
|
||||
}).should('not.exist');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 1, item: { id: SAVED_QUERY_ID } },
|
||||
options: { timeout: 3000 },
|
||||
}).should('not.exist');
|
||||
});
|
||||
|
||||
it('should run query and enable ecs mapping', () => {
|
||||
const cmd = Cypress.platform === 'darwin' ? '{meta}{enter}' : '{ctrl}{enter}';
|
||||
cy.contains('New live query').click();
|
||||
selectAllAgents();
|
||||
inputQuery('select * from uptime;');
|
||||
cy.wait(500);
|
||||
// checking submit by clicking cmd+enter
|
||||
inputQuery(cmd);
|
||||
checkResults();
|
||||
checkActionItemsInResults({
|
||||
lens: false,
|
||||
discover: false,
|
||||
cases: true,
|
||||
timeline: false,
|
||||
});
|
||||
cy.react('EuiDataGridHeaderCellWrapper', {
|
||||
props: { id: 'osquery.days.number', index: 1 },
|
||||
}).should('exist');
|
||||
cy.react('EuiDataGridHeaderCellWrapper', {
|
||||
props: { id: 'osquery.hours.number', index: 2 },
|
||||
}).should('exist');
|
||||
|
||||
cy.react('EuiAccordionClass', { props: { buttonContent: 'Advanced' } })
|
||||
.last()
|
||||
.click();
|
||||
|
||||
typeInECSFieldInput('message{downArrow}{enter}');
|
||||
typeInOsqueryFieldInput('days{downArrow}{enter}');
|
||||
submitQuery();
|
||||
|
||||
checkResults();
|
||||
cy.react('EuiDataGridHeaderCellWrapper', {
|
||||
props: { id: 'message', index: 1 },
|
||||
}).should('exist');
|
||||
cy.react('EuiDataGridHeaderCellWrapper', {
|
||||
props: { id: 'osquery.days.number', index: 2 },
|
||||
}).within(() => {
|
||||
cy.get('.euiToolTipAnchor').within(() => {
|
||||
cy.get('svg').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('to click the edit button and edit pack', () => {
|
||||
navigateTo('/app/osquery/saved_queries');
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 1, item: { id: savedQueryName } },
|
||||
}).click();
|
||||
cy.contains('Custom key/value pairs.').should('exist');
|
||||
cy.contains('Hours of uptime').should('exist');
|
||||
cy.get('[data-test-subj="ECSMappingEditorForm"]')
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.react('EuiButtonIcon', { props: { iconType: 'trash' } }).click();
|
||||
});
|
||||
cy.react('EuiButton').contains('Update query').click();
|
||||
cy.wait(5000);
|
||||
|
||||
cy.react('CustomItemAction', {
|
||||
props: { index: 1, item: { id: savedQueryName } },
|
||||
}).click();
|
||||
cy.contains('Custom key/value pairs').should('not.exist');
|
||||
cy.contains('Hours of uptime').should('not.exist');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { checkOsqueryResponseActionsPermissions } from '../../tasks/response_actions';
|
||||
|
||||
describe(
|
||||
'App Features for Enpoint Complete PLI',
|
||||
{
|
||||
tags: [tag.SERVERLESS],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [
|
||||
{ product_line: 'endpoint', product_tier: 'complete' },
|
||||
{ product_line: 'security', product_tier: 'complete' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => checkOsqueryResponseActionsPermissions(true)
|
||||
);
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { checkOsqueryResponseActionsPermissions } from '../../tasks/response_actions';
|
||||
|
||||
describe(
|
||||
'App Features for Endpoint Essentials PLI',
|
||||
{
|
||||
tags: [tag.SERVERLESS],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [
|
||||
{ product_line: 'security', product_tier: 'essentials' },
|
||||
{ product_line: 'endpoint', product_tier: 'essentials' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => checkOsqueryResponseActionsPermissions(false)
|
||||
);
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { checkOsqueryResponseActionsPermissions } from '../../tasks/response_actions';
|
||||
|
||||
describe(
|
||||
'App Features for Security Complete PLI',
|
||||
{
|
||||
tags: [tag.SERVERLESS],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [{ product_line: 'security', product_tier: 'complete' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => checkOsqueryResponseActionsPermissions(false)
|
||||
);
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { tag } from '../../tags';
|
||||
import { checkOsqueryResponseActionsPermissions } from '../../tasks/response_actions';
|
||||
|
||||
describe(
|
||||
'App Features for Security Essentials PLI',
|
||||
{
|
||||
tags: [tag.SERVERLESS],
|
||||
env: {
|
||||
ftrConfig: { productTypes: [{ product_line: 'security', product_tier: 'essentials' }] },
|
||||
},
|
||||
},
|
||||
() => checkOsqueryResponseActionsPermissions(false)
|
||||
);
|
|
@ -29,6 +29,8 @@
|
|||
module.exports = (on: any, config: any) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('@cypress/code-coverage/task')(on, config);
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
|
|
|
@ -23,22 +23,37 @@
|
|||
// ***********************************************************
|
||||
|
||||
// force ESM in this module
|
||||
import type { SecuritySolutionDescribeBlockFtrConfig } from '@kbn/security-solution-plugin/scripts/run_cypress/utils';
|
||||
|
||||
export {};
|
||||
|
||||
import 'cypress-react-selector';
|
||||
import registerCypressGrep from '@cypress/grep';
|
||||
|
||||
import type { ServerlessRoleName } from './roles';
|
||||
import { login } from '../tasks/login';
|
||||
|
||||
registerCypressGrep();
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace Cypress {
|
||||
interface SuiteConfigOverrides {
|
||||
env?: {
|
||||
ftrConfig: SecuritySolutionDescribeBlockFtrConfig;
|
||||
};
|
||||
}
|
||||
|
||||
interface Chainable {
|
||||
getBySel(...args: Parameters<Cypress.Chainable['get']>): Chainable<JQuery<HTMLElement>>;
|
||||
|
||||
getBySelContains(
|
||||
...args: Parameters<Cypress.Chainable['get']>
|
||||
): Chainable<JQuery<HTMLElement>>;
|
||||
|
||||
clickOutside(): Chainable<JQuery<HTMLBodyElement>>;
|
||||
|
||||
login(role?: ServerlessRoleName | 'elastic'): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +72,8 @@ Cypress.Commands.add(
|
|||
() => cy.get('body').click(0, 0) // 0,0 here are the x and y coordinates
|
||||
);
|
||||
|
||||
Cypress.Commands.add('login', login);
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
Cypress.on('uncaught:exception', () => false);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
soc_manager:
|
||||
applications:
|
||||
- application: discover
|
||||
privileges:
|
||||
- all
|
||||
resources: "*"
|
||||
- application: visualize
|
||||
privileges:
|
||||
- read
|
||||
resources: "*"
|
||||
- application: observabilityCases
|
||||
privileges:
|
||||
- all
|
||||
resources: "*"
|
||||
- application: securitySolutionCases
|
||||
privileges:
|
||||
- all
|
||||
resources: "*"
|
||||
- application: infrastructure
|
||||
privileges:
|
||||
- read
|
||||
resources: "*"
|
||||
- application: indexPatterns
|
||||
privileges:
|
||||
- all
|
||||
resources: "*"
|
||||
|
||||
# custom roles for osquery lack of permission testing
|
||||
reader:
|
||||
indices:
|
||||
- names:
|
||||
- logs-*
|
||||
privileges:
|
||||
- read
|
||||
- write
|
||||
applications:
|
||||
- application: osquery
|
||||
privileges:
|
||||
- read
|
||||
resources: "*"
|
8
x-pack/plugins/osquery/cypress/support/roles.ts
Normal file
8
x-pack/plugins/osquery/cypress/support/roles.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export { ServerlessRoleName } from '../../../../test_serverless/shared/lib/security/types';
|
12
x-pack/plugins/osquery/cypress/tags.ts
Normal file
12
x-pack/plugins/osquery/cypress/tags.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export const tag = {
|
||||
SERVERLESS: '@serverless',
|
||||
ESS: '@ess',
|
||||
BROKEN_IN_SERVERLESS: '@brokenInServerless',
|
||||
};
|
|
@ -103,6 +103,7 @@ export const loadPack = (payload: Partial<PackItem> = {}, space = 'default') =>
|
|||
headers: {
|
||||
'Elastic-Api-Version': API_VERSIONS.public.v1,
|
||||
},
|
||||
|
||||
url: `/s/${space}/api/osquery/packs`,
|
||||
}).then((response) => response.body.data);
|
||||
|
||||
|
@ -293,4 +294,8 @@ export const loadAgentPolicy = () =>
|
|||
}).then((response) => response.body.item);
|
||||
|
||||
export const cleanupAgentPolicy = (agentPolicyId: string) =>
|
||||
request({ method: 'POST', body: { agentPolicyId }, url: '/api/fleet/agent_policies/delete' });
|
||||
request({
|
||||
method: 'POST',
|
||||
body: { agentPolicyId },
|
||||
url: '/api/fleet/agent_policies/delete',
|
||||
});
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
*/
|
||||
|
||||
export const API_AUTH = {
|
||||
user: Cypress.env('ELASTICSEARCH_USERNAME'),
|
||||
pass: Cypress.env('ELASTICSEARCH_PASSWORD'),
|
||||
user: Cypress.env('KIBANA_USERNAME') ?? Cypress.env('ELASTICSEARCH_USERNAME'),
|
||||
pass: Cypress.env('KIBANA_PASSWORD') ?? Cypress.env('ELASTICSEARCH_PASSWORD'),
|
||||
};
|
||||
|
||||
export const API_HEADERS = { 'kbn-xsrf': 'cypress' };
|
||||
export const API_HEADERS = {
|
||||
'kbn-xsrf': 'cypress',
|
||||
'x-elastic-internal-origin': 'security-solution',
|
||||
};
|
||||
|
||||
export const request = <T = unknown>(
|
||||
options: Partial<Cypress.RequestOptions>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { LIVE_QUERY_EDITOR } from '../screens/live_query';
|
||||
import { ROLE, login } from './login';
|
||||
import { ServerlessRoleName } from '../support/roles';
|
||||
|
||||
export const DEFAULT_QUERY = 'select * from processes;';
|
||||
export const BIG_QUERY = 'select * from processes, users limit 110;';
|
||||
|
@ -101,9 +101,9 @@ export const toggleRuleOffAndOn = (ruleName: string) => {
|
|||
};
|
||||
|
||||
export const loadRuleAlerts = (ruleName: string) => {
|
||||
login(ROLE.soc_manager);
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
cy.visit('/app/security/rules');
|
||||
cy.contains(ruleName).click();
|
||||
clickRuleName(ruleName);
|
||||
cy.getBySel('alertsTable').within(() => {
|
||||
cy.getBySel('expand-event')
|
||||
.first()
|
||||
|
@ -170,3 +170,7 @@ export const takeOsqueryActionWithParams = () => {
|
|||
submitQuery();
|
||||
cy.getBySel('dataGridHeader').should('contain', 'tags', { timeout: 6000000 });
|
||||
};
|
||||
|
||||
export const clickRuleName = (ruleName: string) => {
|
||||
cy.contains('a[data-test-subj="ruleName"]', ruleName).click({ force: true });
|
||||
};
|
||||
|
|
|
@ -5,341 +5,82 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as yaml from 'js-yaml';
|
||||
import type { UrlObject } from 'url';
|
||||
import Url from 'url';
|
||||
import type { Role } from '@kbn/security-plugin/common';
|
||||
// import { request } from '@kbn/security-solution-plugin/public/management/cypress/tasks/common';
|
||||
import { isLocalhost } from '@kbn/security-solution-plugin/scripts/endpoint/common/is_localhost';
|
||||
import { request } from './common';
|
||||
import adminRole from '../../scripts/roles_users/admin/role.json';
|
||||
import alertTestRole from '../../scripts/roles_users/alert_test/role.json';
|
||||
import noneRole from '../../scripts/roles_users/none/role.json';
|
||||
import platformEngineerRole from '../../scripts/roles_users/platform_engineer/role.json';
|
||||
import readerRole from '../../scripts/roles_users/reader/role.json';
|
||||
import socManagerRole from '../../scripts/roles_users/soc_manager/role.json';
|
||||
import t1AnalystRole from '../../scripts/roles_users/t1_analyst/role.json';
|
||||
import t2AnalystRole from '../../scripts/roles_users/t2_analyst/role.json';
|
||||
|
||||
export enum ROLE {
|
||||
soc_manager = 'soc_manager',
|
||||
reader = 'reader',
|
||||
t1_analyst = 't1_analyst',
|
||||
t2_analyst = 't2_analyst',
|
||||
platform_engineer = 'platform_engineer',
|
||||
admin = 'admin', // base: ['all']
|
||||
alert_test = 'alert_test',
|
||||
none = 'none',
|
||||
}
|
||||
|
||||
export const rolesMapping: { [key in ROLE]: Omit<Role, 'name'> } = {
|
||||
admin: adminRole,
|
||||
alert_test: alertTestRole,
|
||||
none: noneRole,
|
||||
platform_engineer: platformEngineerRole,
|
||||
reader: readerRole,
|
||||
soc_manager: socManagerRole,
|
||||
t1_analyst: t1AnalystRole,
|
||||
t2_analyst: t2AnalystRole,
|
||||
};
|
||||
import { STANDARD_HTTP_HEADERS } from '../../../../test_serverless/shared/lib/security/default_http_headers';
|
||||
import { ServerlessRoleName } from '../support/roles';
|
||||
|
||||
/**
|
||||
* Credentials in the `kibana.dev.yml` config file will be used to authenticate
|
||||
* with Kibana when credentials are not provided via environment variables
|
||||
*/
|
||||
const KIBANA_DEV_YML_PATH = '../../../config/kibana.dev.yml';
|
||||
|
||||
/**
|
||||
* The configuration path in `kibana.dev.yml` to the username to be used when
|
||||
* authenticating with Kibana.
|
||||
*/
|
||||
const ELASTICSEARCH_USERNAME_CONFIG_PATH = 'config.elasticsearch.username';
|
||||
|
||||
/**
|
||||
* The configuration path in `kibana.dev.yml` to the password to be used when
|
||||
* authenticating with Kibana.
|
||||
*/
|
||||
const ELASTICSEARCH_PASSWORD_CONFIG_PATH = 'config.elasticsearch.password';
|
||||
|
||||
/**
|
||||
* The `CYPRESS_ELASTICSEARCH_USERNAME` environment variable specifies the
|
||||
* username to be used when authenticating with Kibana
|
||||
*/
|
||||
const ELASTICSEARCH_USERNAME = 'ELASTICSEARCH_USERNAME';
|
||||
|
||||
/**
|
||||
* The `CYPRESS_ELASTICSEARCH_PASSWORD` environment variable specifies the
|
||||
* username to be used when authenticating with Kibana
|
||||
*/
|
||||
const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD';
|
||||
|
||||
/**
|
||||
* The Kibana server endpoint used for authentication
|
||||
*/
|
||||
const LOGIN_API_ENDPOINT = '/internal/security/login';
|
||||
|
||||
/**
|
||||
* cy.visit will default to the baseUrl which uses the default kibana test user
|
||||
* This function will override that functionality in cy.visit by building the baseUrl
|
||||
* directly from the environment variables set up in x-pack/test/security_solution_cypress/runner.ts
|
||||
* Send login via API
|
||||
* @param username
|
||||
* @param password
|
||||
*
|
||||
* @param role string role/user to log in with
|
||||
* @param route string route to visit
|
||||
* @private
|
||||
*/
|
||||
export const getUrlWithRoute = (role: ROLE, route: string) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
const kibana = new URL(String(url));
|
||||
const theUrl = `${Url.format({
|
||||
auth: `${role}:changeme`,
|
||||
username: role,
|
||||
password: 'changeme',
|
||||
protocol: kibana.protocol.replace(':', ''),
|
||||
hostname: kibana.hostname,
|
||||
port: kibana.port,
|
||||
} as UrlObject)}${route.startsWith('/') ? '' : '/'}${route}`;
|
||||
cy.log(`origin: ${theUrl}`);
|
||||
const sendApiLoginRequest = (
|
||||
username: string,
|
||||
password: string
|
||||
): Cypress.Chainable<{ username: string; password: string }> => {
|
||||
const url = new URL(Cypress.config().baseUrl ?? '');
|
||||
url.pathname = '/internal/security/login';
|
||||
|
||||
return theUrl;
|
||||
};
|
||||
cy.log(`Authenticating [${username}] via ${url.toString()}`);
|
||||
|
||||
interface User {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a URL with basic auth using the passed in user.
|
||||
*
|
||||
* @param user the user information to build the basic auth with
|
||||
* @param route string route to visit
|
||||
*/
|
||||
export const constructUrlWithUser = (user: User, route: string) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
const kibana = new URL(String(url));
|
||||
const hostname = kibana.hostname;
|
||||
const username = user.username;
|
||||
const password = user.password;
|
||||
const protocol = kibana.protocol.replace(':', '');
|
||||
const port = kibana.port;
|
||||
|
||||
const path = `${route.startsWith('/') ? '' : '/'}${route}`;
|
||||
const strUrl = `${protocol}://${username}:${password}@${hostname}:${port}${path}`;
|
||||
const builtUrl = new URL(strUrl);
|
||||
|
||||
cy.log(`origin: ${builtUrl.href}`);
|
||||
|
||||
return builtUrl.href;
|
||||
};
|
||||
|
||||
export const getCurlScriptEnvVars = () => ({
|
||||
ELASTICSEARCH_URL: Cypress.env('ELASTICSEARCH_URL'),
|
||||
ELASTICSEARCH_USERNAME: Cypress.env('ELASTICSEARCH_USERNAME'),
|
||||
ELASTICSEARCH_PASSWORD: Cypress.env('ELASTICSEARCH_PASSWORD'),
|
||||
KIBANA_URL: Cypress.config().baseUrl,
|
||||
});
|
||||
|
||||
export const postRoleAndUser = (role: ROLE) => {
|
||||
const rolePrivileges = rolesMapping[role];
|
||||
// post the role
|
||||
request({
|
||||
method: 'PUT',
|
||||
url: `/api/security/role/${role}`,
|
||||
body: rolePrivileges,
|
||||
});
|
||||
|
||||
// post the user associated with the role to elasticsearch
|
||||
request({
|
||||
return request({
|
||||
headers: { ...STANDARD_HTTP_HEADERS },
|
||||
method: 'POST',
|
||||
url: `/internal/security/users/${role}`,
|
||||
body: {
|
||||
username: role,
|
||||
password: Cypress.env(ELASTICSEARCH_PASSWORD),
|
||||
roles: [role],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteRoleAndUser = (role: ROLE) => {
|
||||
request({
|
||||
method: 'DELETE',
|
||||
url: `/internal/security/users/${role}`,
|
||||
});
|
||||
request({
|
||||
method: 'DELETE',
|
||||
url: `/api/security/role/${role}`,
|
||||
});
|
||||
};
|
||||
|
||||
export const loginWithUser = (user: User) => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
|
||||
request({
|
||||
url: url.toString(),
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: url && !url.includes('localhost') ? 'cloud-basic' : 'basic',
|
||||
providerName: isLocalhost(url.hostname) ? 'basic' : 'cloud-basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username: user.username,
|
||||
password: user.password,
|
||||
username,
|
||||
password,
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: constructUrlWithUser(user, LOGIN_API_ENDPOINT),
|
||||
});
|
||||
}).then(() => ({
|
||||
username,
|
||||
password,
|
||||
}));
|
||||
};
|
||||
|
||||
export const loginWithRole = async (role: ROLE) => {
|
||||
postRoleAndUser(role);
|
||||
const theUrl = Url.format({
|
||||
auth: `${role}:changeme`,
|
||||
username: role,
|
||||
password: 'changeme',
|
||||
protocol: Cypress.env('protocol'),
|
||||
hostname: Cypress.env('hostname'),
|
||||
port: Cypress.env('configport'),
|
||||
} as UrlObject);
|
||||
cy.log(`origin: ${theUrl}`);
|
||||
cy.session([role], () => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username: role,
|
||||
password: 'changeme',
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: getUrlWithRoute(role, LOGIN_API_ENDPOINT),
|
||||
});
|
||||
});
|
||||
};
|
||||
interface CyLoginTask {
|
||||
(user?: ServerlessRoleName): ReturnType<typeof sendApiLoginRequest>;
|
||||
|
||||
/**
|
||||
* Login using any username/password
|
||||
* @param username
|
||||
* @param password
|
||||
*/
|
||||
with(username: string, password: string): ReturnType<typeof sendApiLoginRequest>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana using, if specified, credentials specified by
|
||||
* environment variables. The credentials in `kibana.dev.yml` will be used
|
||||
* for authentication when the environment variables are unset.
|
||||
*
|
||||
* To speed the execution of tests, prefer this non-interactive authentication,
|
||||
* which is faster than authentication via Kibana's interactive login page.
|
||||
* Login to Kibana using API (not login page). By default, user will be logged in using
|
||||
* the username and password defined via `KIBANA_USERNAME` and `KIBANA_PASSWORD` cypress env
|
||||
* variables.
|
||||
* @param user Defaults to `soc_manager`
|
||||
*/
|
||||
export const login = (role?: ROLE) => {
|
||||
if (role != null) {
|
||||
loginWithRole(role);
|
||||
} else if (credentialsProvidedByEnvironment()) {
|
||||
loginViaEnvironmentCredentials();
|
||||
export const login: CyLoginTask = (
|
||||
user: ServerlessRoleName | 'elastic' = ServerlessRoleName.SOC_MANAGER
|
||||
): ReturnType<typeof sendApiLoginRequest> => {
|
||||
let username = Cypress.env('KIBANA_USERNAME');
|
||||
let password = Cypress.env('KIBANA_PASSWORD');
|
||||
|
||||
if (user && user !== 'elastic') {
|
||||
// @ts-expect-error update type
|
||||
return cy.task('loadUserAndRole', { name: user }).then((loadedUser: LoadedRoleAndUser) => {
|
||||
username = loadedUser.username;
|
||||
password = loadedUser.password;
|
||||
|
||||
return sendApiLoginRequest(username, password);
|
||||
});
|
||||
} else {
|
||||
loginViaConfig();
|
||||
return sendApiLoginRequest(username, password);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns `true` if the credentials used to login to Kibana are provided
|
||||
* via environment variables
|
||||
*/
|
||||
const credentialsProvidedByEnvironment = (): boolean =>
|
||||
Cypress.env(ELASTICSEARCH_USERNAME) != null && Cypress.env(ELASTICSEARCH_PASSWORD) != null;
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana by reading credentials from the
|
||||
* `CYPRESS_ELASTICSEARCH_USERNAME` and `CYPRESS_ELASTICSEARCH_PASSWORD`
|
||||
* environment variables, and POSTing the username and password directly to
|
||||
* Kibana's `/internal/security/login` endpoint, bypassing the login page (for speed).
|
||||
*/
|
||||
const loginViaEnvironmentCredentials = () => {
|
||||
const url = Cypress.config().baseUrl;
|
||||
|
||||
cy.log(
|
||||
`Authenticating via environment credentials from the \`CYPRESS_${ELASTICSEARCH_USERNAME}\` and \`CYPRESS_${ELASTICSEARCH_PASSWORD}\` environment variables`
|
||||
);
|
||||
|
||||
const username = Cypress.env(ELASTICSEARCH_USERNAME);
|
||||
const password = Cypress.env(ELASTICSEARCH_PASSWORD);
|
||||
|
||||
// programmatically authenticate without interacting with the Kibana login page
|
||||
cy.session([username, password], () => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: url && !url.includes('localhost') ? 'cloud-basic' : 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-env' },
|
||||
method: 'POST',
|
||||
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana by reading credentials from the
|
||||
* `kibana.dev.yml` file and POSTing the username and password directly to
|
||||
* Kibana's `/internal/security/login` endpoint, bypassing the login page (for speed).
|
||||
*/
|
||||
const loginViaConfig = () => {
|
||||
cy.log(
|
||||
`Authenticating via config credentials \`${ELASTICSEARCH_USERNAME_CONFIG_PATH}\` and \`${ELASTICSEARCH_PASSWORD_CONFIG_PATH}\` from \`${KIBANA_DEV_YML_PATH}\``
|
||||
);
|
||||
|
||||
// read the login details from `kibana.dev.yaml`
|
||||
cy.readFile(KIBANA_DEV_YML_PATH).then((kibanaDevYml) => {
|
||||
const config = yaml.safeLoad(kibanaDevYml);
|
||||
|
||||
const username = 'elastic';
|
||||
const password = config.elasticsearch.password;
|
||||
|
||||
// programmatically authenticate without interacting with the Kibana login page
|
||||
cy.session([username, password], () => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the configured auth details that were used to spawn cypress
|
||||
*
|
||||
* @returns the default Elasticsearch username and password for this environment
|
||||
*/
|
||||
export const getEnvAuth = (): User => {
|
||||
if (credentialsProvidedByEnvironment()) {
|
||||
return {
|
||||
username: Cypress.env(ELASTICSEARCH_USERNAME),
|
||||
password: Cypress.env(ELASTICSEARCH_PASSWORD),
|
||||
};
|
||||
} else {
|
||||
let user: User = { username: '', password: '' };
|
||||
cy.readFile(KIBANA_DEV_YML_PATH).then((devYml) => {
|
||||
const config = yaml.safeLoad(devYml);
|
||||
user = { username: config.elasticsearch.username, password: config.elasticsearch.password };
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana, visits the specified `url`, and waits for the
|
||||
* Kibana global nav to be displayed before continuing
|
||||
*/
|
||||
export const loginAndWaitForPage = (url: string) => {
|
||||
login();
|
||||
cy.visit(url);
|
||||
};
|
||||
login.with = (username: string, password: string): ReturnType<typeof sendApiLoginRequest> =>
|
||||
sendApiLoginRequest(username, password);
|
||||
|
|
|
@ -5,9 +5,54 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { clickRuleName } from './live_query';
|
||||
import { ServerlessRoleName } from '../support/roles';
|
||||
import { cleanupRule, loadRule } from './api_fixtures';
|
||||
import { closeDateTabIfVisible } from './integrations';
|
||||
|
||||
export const RESPONSE_ACTIONS_ITEM_0 = 'response-actions-list-item-0';
|
||||
export const RESPONSE_ACTIONS_ITEM_1 = 'response-actions-list-item-1';
|
||||
export const RESPONSE_ACTIONS_ITEM_2 = 'response-actions-list-item-2';
|
||||
export const RESPONSE_ACTIONS_ITEM_3 = 'response-actions-list-item-3';
|
||||
|
||||
export const OSQUERY_RESPONSE_ACTION_ADD_BUTTON = 'Osquery-response-action-type-selection-option';
|
||||
export const ENDPOINT_RESPONSE_ACTION_ADD_BUTTON =
|
||||
'Endpoint Security-response-action-type-selection-option';
|
||||
|
||||
export const checkOsqueryResponseActionsPermissions = (enabled: boolean) => {
|
||||
let ruleId: string;
|
||||
let ruleName: string;
|
||||
|
||||
before(() => {
|
||||
loadRule().then((data) => {
|
||||
ruleId = data.id;
|
||||
ruleName = data.name;
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
cleanupRule(ruleId);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(ServerlessRoleName.SOC_MANAGER);
|
||||
});
|
||||
|
||||
it(`response actions should ${enabled ? 'be available ' : 'not be available'}`, () => {
|
||||
cy.visit('/app/security/rules');
|
||||
clickRuleName(ruleName);
|
||||
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();
|
||||
if (enabled) {
|
||||
cy.getBySel(ENDPOINT_RESPONSE_ACTION_ADD_BUTTON).click();
|
||||
cy.contains('Query is a required field');
|
||||
cy.contains('Select an endpoint response action.');
|
||||
} else {
|
||||
cy.contains('Upgrade your license to Endpoint Complete to use Osquery Response Actions.');
|
||||
cy.getBySel(ENDPOINT_RESPONSE_ACTION_ADD_BUTTON).should('be.disabled');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -62,6 +62,7 @@ export const getSavedQueriesComplexTest = () =>
|
|||
cy.getBySel('pagination-button-next').click().wait(500).click();
|
||||
cy.contains('columns hidden').should('exist');
|
||||
|
||||
// enter fullscreen
|
||||
cy.getBySel(RESULTS_TABLE_BUTTON).trigger('mouseover');
|
||||
cy.contains(/Enter fullscreen$/).should('not.exist');
|
||||
cy.contains('Exit fullscreen').should('exist');
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
"extends": "../../../../tsconfig.base.json",
|
||||
"include": [
|
||||
"**/*",
|
||||
"../cypress.config.ts"
|
||||
"../cypress.config.ts",
|
||||
"../serverless_cypress.config.ts",
|
||||
"../../../test_serverless/shared/lib"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
|
@ -25,7 +27,6 @@
|
|||
"path": "../tsconfig.json",
|
||||
"force": true
|
||||
},
|
||||
"@kbn/security-plugin",
|
||||
"@kbn/security-solution-plugin",
|
||||
"@kbn/fleet-plugin",
|
||||
"@kbn/cases-plugin"
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
"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",
|
||||
"cypress:serverless:open": "node ../security_solution/scripts/start_cypress_parallel open --config-file ../osquery/serverless_cypress.config.ts --ftr-config-file ../../../x-pack/test/osquery_cypress/serverless_cli_config",
|
||||
"cypress:serverless:run": "node ../security_solution/scripts/start_cypress_parallel run --config-file ../osquery/serverless_cypress.config.ts --ftr-config-file ../../../x-pack/test/osquery_cypress/serverless_cli_config --concurrency 1",
|
||||
"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"
|
||||
|
|
43
x-pack/plugins/osquery/serverless_cypress.config.ts
Normal file
43
x-pack/plugins/osquery/serverless_cypress.config.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
// eslint-disable-next-line @kbn/imports/no_boundary_crossing
|
||||
import { setupUserDataLoader } from '../../test_serverless/functional/test_suites/security/cypress/support/setup_data_loader_tasks';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default defineCypressConfig({
|
||||
defaultCommandTimeout: 60000,
|
||||
execTimeout: 60000,
|
||||
pageLoadTimeout: 60000,
|
||||
responseTimeout: 60000,
|
||||
screenshotsFolder: '../../../target/kibana-osquery/cypress/screenshots',
|
||||
trashAssetsBeforeRuns: false,
|
||||
video: false,
|
||||
viewportHeight: 946,
|
||||
viewportWidth: 1680,
|
||||
|
||||
env: {
|
||||
'cypress-react-selector': {
|
||||
root: '#osquery-app',
|
||||
},
|
||||
grepFilterSpecs: true,
|
||||
grepTags: '@serverless --@brokenInServerless',
|
||||
grepOmitFiltered: true,
|
||||
},
|
||||
e2e: {
|
||||
specPattern: './cypress/e2e/**/*.cy.ts',
|
||||
experimentalRunAllSpecs: true,
|
||||
experimentalMemoryManagement: true,
|
||||
numTestsKeptInMemory: 3,
|
||||
setupNodeEvents: (on, config) => {
|
||||
setupUserDataLoader(on, config, { additionalRoleName: 'viewer' });
|
||||
|
||||
return config;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -5,6 +5,7 @@
|
|||
},
|
||||
"exclude": [
|
||||
"cypress.config.ts",
|
||||
"serverless_cypress.config.ts",
|
||||
"target/**/*",
|
||||
],
|
||||
"include": [
|
||||
|
@ -15,6 +16,7 @@
|
|||
"scripts/**/**.json",
|
||||
"server/**/*",
|
||||
"cypress.config.ts",
|
||||
"serverless_cypress.config.ts",
|
||||
"../../../typings/**/*",
|
||||
// ECS and Osquery schema files
|
||||
"public/common/schemas/*/**.json",
|
||||
|
@ -74,6 +76,6 @@
|
|||
"@kbn/core-lifecycle-browser",
|
||||
"@kbn/core-saved-objects-server",
|
||||
"@kbn/monaco",
|
||||
"@kbn/io-ts-utils"
|
||||
"@kbn/io-ts-utils",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import type {
|
|||
declare global {
|
||||
namespace Cypress {
|
||||
interface SuiteConfigOverrides {
|
||||
env: {
|
||||
env?: {
|
||||
ftrConfig: SecuritySolutionDescribeBlockFtrConfig;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { generateRandomStringName } from '@kbn/osquery-plugin/cypress/tasks/integrations';
|
||||
import { generateRandomStringName } from '../../../tasks/utils';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointRuleAlerts } from '../../../tasks/index_endpoint_rule_alerts';
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { generateRandomStringName } from '@kbn/osquery-plugin/cypress/tasks/integrations';
|
||||
import { disableExpandableFlyoutAdvancedSettings } from '../../../tasks/common';
|
||||
import { APP_ALERTS_PATH } from '../../../../../../common/constants';
|
||||
import { closeAllToasts } from '../../../tasks/toasts';
|
||||
import { fillUpNewRule } from '../../../tasks/response_actions';
|
||||
import { login, loginWithRole, ROLE } from '../../../tasks/login';
|
||||
import { generateRandomStringName } from '../../../tasks/utils';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import { indexEndpointRuleAlerts } from '../../../tasks/index_endpoint_rule_alerts';
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { generateRandomStringName } from '@kbn/osquery-plugin/cypress/tasks/integrations';
|
||||
import { disableExpandableFlyoutAdvancedSettings } from '../../../tasks/common';
|
||||
import { generateRandomStringName } from '../../../tasks/utils';
|
||||
import { APP_ALERTS_PATH } from '../../../../../../common/constants';
|
||||
import { closeAllToasts } from '../../../tasks/toasts';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export const generateRandomStringName = (length: number) =>
|
||||
Array.from({ length }, () => Math.random().toString(36).substring(2));
|
|
@ -35,6 +35,5 @@
|
|||
"@kbn/test",
|
||||
"@kbn/repo-info",
|
||||
"@kbn/data-views-plugin",
|
||||
"@kbn/osquery-plugin/cypress",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -266,9 +266,18 @@ export const cli = () => {
|
|||
}
|
||||
|
||||
if (hasFleetServerArgs) {
|
||||
vars.kbnTestServer.serverArgs.push(
|
||||
`--xpack.fleet.agents.fleet_server.hosts=["https://${hostRealIp}:${fleetServerPort}"]`
|
||||
);
|
||||
vars.kbnTestServer.serverArgs.push(
|
||||
`--xpack.fleet.agents.elasticsearch.host=http://${hostRealIp}:${esPort}`
|
||||
);
|
||||
|
||||
if (vars.serverless) {
|
||||
vars.kbnTestServer.serverArgs.push(
|
||||
`--xpack.fleet.internal.fleetServerStandalone=false`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Serverless Specific
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
*/
|
||||
|
||||
export async function getLatestVersion(): Promise<string> {
|
||||
return '8.9.0-SNAPSHOT';
|
||||
return '8.10.0-SNAPSHOT';
|
||||
}
|
||||
|
|
46
x-pack/test/osquery_cypress/serverless_cli_config.ts
Normal file
46
x-pack/test/osquery_cypress/serverless_cli_config.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
import { startOsqueryCypress } from './runner';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const securitySolutionCypressConfig = await readConfigFile(
|
||||
require.resolve(
|
||||
'../../test_serverless/functional/test_suites/security/cypress/security_config.base.ts'
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
...securitySolutionCypressConfig.getAll(),
|
||||
|
||||
esTestCluster: {
|
||||
...securitySolutionCypressConfig.get('esTestCluster'),
|
||||
serverArgs: [
|
||||
...securitySolutionCypressConfig.get('esTestCluster.serverArgs'),
|
||||
'http.host=0.0.0.0',
|
||||
],
|
||||
},
|
||||
|
||||
kbnTestServer: {
|
||||
...securitySolutionCypressConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...securitySolutionCypressConfig.get('kbnTestServer.serverArgs'),
|
||||
`--xpack.fleet.agents.fleet_server.hosts=["https://host.docker.internal:8220"]`,
|
||||
`--xpack.fleet.agents.elasticsearch.host=http://host.docker.internal:${securitySolutionCypressConfig.get(
|
||||
'servers.elasticsearch.port'
|
||||
)}`,
|
||||
`--xpack.fleet.packages.0.name=osquery_manager`,
|
||||
`--xpack.fleet.packages.0.version=latest`,
|
||||
`--xpack.fleet.internal.fleetServerStandalone=false`,
|
||||
],
|
||||
},
|
||||
|
||||
testRunner: startOsqueryCypress,
|
||||
};
|
||||
}
|
|
@ -16,12 +16,17 @@ import {
|
|||
} from '@kbn/fleet-plugin/common/types';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
|
||||
export const DEFAULT_HEADERS = Object.freeze({
|
||||
'x-elastic-internal-product': 'security-solution',
|
||||
});
|
||||
|
||||
export const getInstalledIntegration = async (kbnClient: KbnClient, integrationName: string) => {
|
||||
const {
|
||||
data: { item },
|
||||
} = await kbnClient.request<{ item: PackagePolicy }>({
|
||||
method: 'GET',
|
||||
path: `/api/fleet/epm/packages/${integrationName}`,
|
||||
headers: DEFAULT_HEADERS,
|
||||
});
|
||||
|
||||
return item;
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
*/
|
||||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
import { setupDataLoaderTasks } from './support/setup_data_loader_tasks';
|
||||
import { dataLoaders as setupEndpointDataLoaders } from '@kbn/security-solution-plugin/public/management/cypress/support/data_loaders';
|
||||
import { setupUserDataLoader } from './support/setup_data_loader_tasks';
|
||||
|
||||
export default defineCypressConfig({
|
||||
defaultCommandTimeout: 60000,
|
||||
|
@ -25,7 +26,9 @@ export default defineCypressConfig({
|
|||
supportFile: './support/e2e.js',
|
||||
specPattern: './e2e/**/*.cy.ts',
|
||||
setupNodeEvents: (on, config) => {
|
||||
setupDataLoaderTasks(on, config);
|
||||
// Reuse data loaders from endpoint management cypress setup
|
||||
setupEndpointDataLoaders(on, config);
|
||||
setupUserDataLoader(on, config, {});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -42,7 +42,7 @@ export interface LoadUserAndRoleCyTaskOptions {
|
|||
declare global {
|
||||
namespace Cypress {
|
||||
interface SuiteConfigOverrides {
|
||||
env: {
|
||||
env?: {
|
||||
ftrConfig: SecuritySolutionDescribeBlockFtrConfig;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,17 +6,22 @@
|
|||
*/
|
||||
|
||||
import { createRuntimeServices } from '@kbn/security-solution-plugin/scripts/endpoint/common/stack_services';
|
||||
import { dataLoaders } from '@kbn/security-solution-plugin/public/management/cypress/support/data_loaders';
|
||||
import { LoadUserAndRoleCyTaskOptions } from '../cypress';
|
||||
import { LoadedRoleAndUser, SecurityRoleAndUserLoader } from '../../../../../shared/lib';
|
||||
import {
|
||||
LoadedRoleAndUser,
|
||||
SecurityRoleAndUserLoader,
|
||||
YamlRoleDefinitions,
|
||||
} from '../../../../../shared/lib';
|
||||
|
||||
export const setupDataLoaderTasks = (
|
||||
interface AdditionalDefinitions {
|
||||
roleDefinitions?: YamlRoleDefinitions;
|
||||
additionalRoleName?: string;
|
||||
}
|
||||
export const setupUserDataLoader = (
|
||||
on: Cypress.PluginEvents,
|
||||
config: Cypress.PluginConfigOptions
|
||||
config: Cypress.PluginConfigOptions,
|
||||
{ roleDefinitions, additionalRoleName }: AdditionalDefinitions
|
||||
) => {
|
||||
// Reuse data loaders from endpoint management cypress setup
|
||||
dataLoaders(on, config);
|
||||
|
||||
const stackServicesPromise = createRuntimeServices({
|
||||
kibanaUrl: config.env.KIBANA_URL,
|
||||
elasticsearchUrl: config.env.ELASTICSEARCH_URL,
|
||||
|
@ -29,7 +34,7 @@ export const setupDataLoaderTasks = (
|
|||
|
||||
const roleAndUserLoaderPromise: Promise<SecurityRoleAndUserLoader> = stackServicesPromise.then(
|
||||
({ kbnClient, log }) => {
|
||||
return new SecurityRoleAndUserLoader(kbnClient, log);
|
||||
return new SecurityRoleAndUserLoader(kbnClient, log, roleDefinitions);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -39,7 +44,7 @@ export const setupDataLoaderTasks = (
|
|||
* @param name
|
||||
*/
|
||||
loadUserAndRole: async ({ name }: LoadUserAndRoleCyTaskOptions): Promise<LoadedRoleAndUser> => {
|
||||
return (await roleAndUserLoaderPromise).load(name);
|
||||
return (await roleAndUserLoaderPromise).load(name, additionalRoleName);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
*/
|
||||
|
||||
export * from './kibana_roles';
|
||||
export * from './types';
|
||||
|
|
|
@ -8,27 +8,15 @@
|
|||
import { safeLoad as loadYaml } from 'js-yaml';
|
||||
import { readFileSync } from 'fs';
|
||||
import * as path from 'path';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { cloneDeep, merge } from 'lodash';
|
||||
import { FeaturesPrivileges, Role, RoleIndexPrivilege } from '@kbn/security-plugin/common';
|
||||
import { ServerlessRoleName } from '../types';
|
||||
|
||||
const ROLES_YAML_FILE_PATH = path.join(__dirname, 'project_controller_security_roles.yml');
|
||||
|
||||
const ROLE_NAMES = [
|
||||
't1_analyst',
|
||||
't2_analyst',
|
||||
't3_analyst',
|
||||
'threat_intelligence_analyst',
|
||||
'rule_author',
|
||||
'soc_manager',
|
||||
'detections_admin',
|
||||
'platform_engineer',
|
||||
'endpoint_operations_analyst',
|
||||
'endpoint_policy_manager',
|
||||
] as const;
|
||||
const ROLE_NAMES = Object.values(ServerlessRoleName);
|
||||
|
||||
export type ServerlessRoleName = typeof ROLE_NAMES[number];
|
||||
|
||||
type YamlRoleDefinitions = Record<
|
||||
export type YamlRoleDefinitions = Record<
|
||||
ServerlessRoleName,
|
||||
{
|
||||
cluster: string[] | null;
|
||||
|
@ -45,10 +33,16 @@ const roleDefinitions = loadYaml(readFileSync(ROLES_YAML_FILE_PATH, 'utf8')) as
|
|||
|
||||
export type ServerlessSecurityRoles = Record<ServerlessRoleName, Role>;
|
||||
|
||||
export const getServerlessSecurityKibanaRoleDefinitions = (): ServerlessSecurityRoles => {
|
||||
export const getServerlessSecurityKibanaRoleDefinitions = (
|
||||
additionalRoleDefinitions?: YamlRoleDefinitions
|
||||
): ServerlessSecurityRoles => {
|
||||
const definitions = cloneDeep(roleDefinitions);
|
||||
const mergedDefinitions: YamlRoleDefinitions = merge(
|
||||
definitions,
|
||||
additionalRoleDefinitions || {}
|
||||
);
|
||||
|
||||
return Object.entries(definitions).reduce((roles, [roleName, definition]) => {
|
||||
return Object.entries(mergedDefinitions).reduce((roles, [roleName, definition]) => {
|
||||
if (!ROLE_NAMES.includes(roleName as ServerlessRoleName)) {
|
||||
throw new Error(
|
||||
`Un-expected role [${roleName}] found in YAML file [${ROLES_YAML_FILE_PATH}]`
|
||||
|
|
|
@ -404,6 +404,10 @@ soc_manager:
|
|||
privileges:
|
||||
- all
|
||||
resources: "*"
|
||||
- application: savedObjectsManagement
|
||||
privileges:
|
||||
- all
|
||||
resources: "*"
|
||||
|
||||
detections_admin:
|
||||
cluster:
|
||||
|
|
|
@ -15,6 +15,7 @@ import { AxiosError } from 'axios';
|
|||
import {
|
||||
getServerlessSecurityKibanaRoleDefinitions,
|
||||
ServerlessSecurityRoles,
|
||||
YamlRoleDefinitions,
|
||||
} from './kibana_roles';
|
||||
import { STANDARD_HTTP_HEADERS } from '../default_http_headers';
|
||||
|
||||
|
@ -46,7 +47,7 @@ export class RoleAndUserLoader<R extends Record<string, Role> = Record<string, R
|
|||
};
|
||||
}
|
||||
|
||||
async load(name: keyof R): Promise<LoadedRoleAndUser> {
|
||||
async load(name: keyof R, additionalRoleName?: string): Promise<LoadedRoleAndUser> {
|
||||
const role = this.roles[name];
|
||||
|
||||
if (!role) {
|
||||
|
@ -56,9 +57,12 @@ export class RoleAndUserLoader<R extends Record<string, Role> = Record<string, R
|
|||
}
|
||||
|
||||
const roleName = role.name;
|
||||
|
||||
const roleNames = [roleName];
|
||||
if (additionalRoleName) {
|
||||
roleNames.push(additionalRoleName);
|
||||
}
|
||||
await this.createRole(role);
|
||||
await this.createUser(roleName, 'changeme', [roleName]);
|
||||
await this.createUser(roleName, 'changeme', roleNames);
|
||||
|
||||
return {
|
||||
role: roleName,
|
||||
|
@ -123,7 +127,11 @@ export class RoleAndUserLoader<R extends Record<string, Role> = Record<string, R
|
|||
}
|
||||
|
||||
export class SecurityRoleAndUserLoader extends RoleAndUserLoader<ServerlessSecurityRoles> {
|
||||
constructor(kbnClient: KbnClient, logger: ToolingLog) {
|
||||
super(kbnClient, logger, getServerlessSecurityKibanaRoleDefinitions());
|
||||
constructor(
|
||||
kbnClient: KbnClient,
|
||||
logger: ToolingLog,
|
||||
additionalRoleDefinitions?: YamlRoleDefinitions
|
||||
) {
|
||||
super(kbnClient, logger, getServerlessSecurityKibanaRoleDefinitions(additionalRoleDefinitions));
|
||||
}
|
||||
}
|
||||
|
|
20
x-pack/test_serverless/shared/lib/security/types.ts
Normal file
20
x-pack/test_serverless/shared/lib/security/types.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export enum ServerlessRoleName {
|
||||
T1_ANALYST = 't1_analyst',
|
||||
T2_ANALYST = 't2_analyst',
|
||||
T3_ANALYST = 't3_analyst',
|
||||
THREAT_INTELLIGENCE_ANALYST = 'threat_intelligence_analyst',
|
||||
RULE_AUTHOR = 'rule_author',
|
||||
SOC_MANAGER = 'soc_manager',
|
||||
DETECTIONS_ADMIN = 'detections_admin',
|
||||
PLATFORM_ENGINEER = 'platform_engineer',
|
||||
ENDPOINT_OPERATIONS_ANALYST = 'endpoint_operations_analyst',
|
||||
ENDPOINT_POLICY_MANAGER = 'endpoint_policy_manager',
|
||||
READER = 'reader', // custom role to test lack of permissions
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue