mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[8.11] [Security Solution][Endpoint] Split defend workflows cypress tests to minimize run times (#170232) (#170299)
# Backport This will backport the following commits from `main` to `8.11`: - [[Security Solution][Endpoint] Split defend workflows cypress tests to minimize run times (#170232)](https://github.com/elastic/kibana/pull/170232) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Ash","email":"1849116+ashokaditya@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-11-01T08:43:38Z","message":"[Security Solution][Endpoint] Split defend workflows cypress tests to minimize run times (#170232)\n\n## Summary\r\n\r\nSplits test suites into multiple files to minimize CI run time.\r\n\r\n- [x] splits tests in\r\n[response_console_actions.cy.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_actions.cy.ts)\r\n- [x] splits\r\n[response_console_mocked_data.cy.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked_data.cy.ts)\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"2789dd78244df46781bcca53a141678fb8c166c3","branchLabelMapping":{"^v8.12.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Defend Workflows","OLM Sprint","v8.11.0","v8.12.0"],"number":170232,"url":"https://github.com/elastic/kibana/pull/170232","mergeCommit":{"message":"[Security Solution][Endpoint] Split defend workflows cypress tests to minimize run times (#170232)\n\n## Summary\r\n\r\nSplits test suites into multiple files to minimize CI run time.\r\n\r\n- [x] splits tests in\r\n[response_console_actions.cy.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_actions.cy.ts)\r\n- [x] splits\r\n[response_console_mocked_data.cy.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked_data.cy.ts)\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"2789dd78244df46781bcca53a141678fb8c166c3"}},"sourceBranch":"main","suggestedTargetBranches":["8.11"],"targetPullRequestStates":[{"branch":"8.11","label":"v8.11.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.12.0","labelRegex":"^v8.12.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/170232","number":170232,"mergeCommit":{"message":"[Security Solution][Endpoint] Split defend workflows cypress tests to minimize run times (#170232)\n\n## Summary\r\n\r\nSplits test suites into multiple files to minimize CI run time.\r\n\r\n- [x] splits tests in\r\n[response_console_actions.cy.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_actions.cy.ts)\r\n- [x] splits\r\n[response_console_mocked_data.cy.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked_data.cy.ts)\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"2789dd78244df46781bcca53a141678fb8c166c3"}}]}] BACKPORT--> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
0b6e79eb33
commit
1015325669
14 changed files with 886 additions and 585 deletions
|
@ -5,13 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getEndpointSecurityPolicyManager } from '../../../../../scripts/endpoint/common/roles_users';
|
||||
import { getRoleWithArtifactReadPrivilege } from '../../fixtures/role_with_artifact_read_privilege';
|
||||
import { getEndpointSecurityPolicyManager } from '../../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager';
|
||||
import { getArtifactsListTestsData } from '../../fixtures/artifacts_page';
|
||||
import { visitPolicyDetailsPage } from '../../screens/policy_details';
|
||||
import {
|
||||
createPerPolicyArtifact,
|
||||
createArtifactList,
|
||||
createPerPolicyArtifact,
|
||||
removeAllArtifacts,
|
||||
removeExceptionsList,
|
||||
yieldFirstPolicyID,
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { PolicyData } from '../../../../../../common/endpoint/types';
|
||||
import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
submitCommand,
|
||||
waitForCommandToBeExecuted,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet';
|
||||
|
||||
import { login } from '../../../tasks/login';
|
||||
import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy';
|
||||
import { createEndpointHost } from '../../../tasks/create_endpoint_host';
|
||||
import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('Execute operations: execute', () => {
|
||||
const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`;
|
||||
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('"execute --command" - should execute a command', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`execute --command "ls -al ${homeFilePath}"`);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('execute');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { PolicyData } from '../../../../../../common/endpoint/types';
|
||||
import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
submitCommand,
|
||||
waitForCommandToBeExecuted,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet';
|
||||
|
||||
import { login } from '../../../tasks/login';
|
||||
import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy';
|
||||
import { createEndpointHost } from '../../../tasks/create_endpoint_host';
|
||||
import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('File operations: get-file and upload', () => {
|
||||
const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`;
|
||||
|
||||
const fileContent = 'This is a test file for the get-file command.';
|
||||
const filePath = `${homeFilePath}/test_file.txt`;
|
||||
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('"get-file --path" - should retrieve a file', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
cy.task('createFileOnEndpoint', {
|
||||
hostname: createdHost.hostname,
|
||||
path: filePath,
|
||||
content: fileContent,
|
||||
});
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`get-file --path ${filePath}`);
|
||||
submitCommand();
|
||||
cy.getByTestSubj('getFileSuccess', { timeout: 60000 }).within(() => {
|
||||
cy.contains('File retrieved from the host.');
|
||||
cy.contains('(ZIP file passcode: elastic)');
|
||||
cy.contains(
|
||||
'Files are periodically deleted to clear storage space. Download and save file locally if needed.'
|
||||
);
|
||||
cy.contains('Click here to download').click();
|
||||
const downloadsFolder = Cypress.config('downloadsFolder');
|
||||
cy.readFile(`${downloadsFolder}/upload.zip`);
|
||||
|
||||
cy.task('uploadFileToEndpoint', {
|
||||
hostname: createdHost.hostname,
|
||||
srcPath: `${downloadsFolder}/upload.zip`,
|
||||
destPath: `${homeFilePath}/upload.zip`,
|
||||
});
|
||||
|
||||
cy.task('readZippedFileContentOnEndpoint', {
|
||||
hostname: createdHost.hostname,
|
||||
path: `${homeFilePath}/upload.zip`,
|
||||
password: 'elastic',
|
||||
}).then((unzippedFileContent) => {
|
||||
expect(unzippedFileContent).to.equal(fileContent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('"upload --file" - should upload a file', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`upload --file`);
|
||||
cy.getByTestSubj('console-arg-file-picker').selectFile(
|
||||
{
|
||||
contents: Cypress.Buffer.from('upload file content here!'),
|
||||
fileName: 'upload_file.txt',
|
||||
lastModified: Date.now(),
|
||||
},
|
||||
{ force: true }
|
||||
);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('upload');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { PolicyData } from '../../../../../../common/endpoint/types';
|
||||
import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services';
|
||||
import {
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForCommandToBeExecuted,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet';
|
||||
import {
|
||||
checkEndpointListForOnlyIsolatedHosts,
|
||||
checkEndpointListForOnlyUnIsolatedHosts,
|
||||
} from '../../../tasks/isolate';
|
||||
|
||||
import { login } from '../../../tasks/login';
|
||||
import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy';
|
||||
import { createEndpointHost } from '../../../tasks/create_endpoint_host';
|
||||
import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('Host Isolation: isolate and release an endpoint', () => {
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('should isolate host from response console', () => {
|
||||
const command = 'isolate';
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyUnIsolatedHosts();
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks(command);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted(command);
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyIsolatedHosts();
|
||||
});
|
||||
|
||||
it('should release host from response console', () => {
|
||||
const command = 'release';
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyIsolatedHosts();
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks(command);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted(command);
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyUnIsolatedHosts();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { PolicyData } from '../../../../../../common/endpoint/types';
|
||||
import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForCommandToBeExecuted,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet';
|
||||
|
||||
import { login } from '../../../tasks/login';
|
||||
import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy';
|
||||
import { createEndpointHost } from '../../../tasks/create_endpoint_host';
|
||||
import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('Processes operations: list, kill and suspend process', () => {
|
||||
let cronPID: string;
|
||||
let newCronPID: string;
|
||||
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('"processes" - should obtain a list of processes', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('processes');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => {
|
||||
['USER', 'PID', 'ENTITY ID', 'COMMAND'].forEach((header) => {
|
||||
cy.contains(header);
|
||||
});
|
||||
|
||||
cy.get('tbody > tr').should('have.length.greaterThan', 0);
|
||||
cy.get('tbody > tr > td').should('contain', '/usr/sbin/cron');
|
||||
cy.get('tbody > tr > td')
|
||||
.contains('/usr/sbin/cron')
|
||||
.parents('td')
|
||||
.siblings('td')
|
||||
.eq(1)
|
||||
.find('span')
|
||||
.then((span) => {
|
||||
cronPID = span.text();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('"kill-process --pid" - should kill a process', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`kill-process --pid ${cronPID}`);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('kill-process');
|
||||
|
||||
performCommandInputChecks('processes');
|
||||
submitCommand();
|
||||
|
||||
cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => {
|
||||
cy.get('tbody > tr > td')
|
||||
.contains('/usr/sbin/cron')
|
||||
.parents('td')
|
||||
.siblings('td')
|
||||
.eq(1)
|
||||
.find('span')
|
||||
.then((span) => {
|
||||
newCronPID = span.text();
|
||||
});
|
||||
});
|
||||
expect(newCronPID).to.not.equal(cronPID);
|
||||
});
|
||||
|
||||
it('"suspend-process --pid" - should suspend a process', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`suspend-process --pid ${newCronPID}`);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('suspend-process');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,19 +8,14 @@
|
|||
import type { PolicyData } from '../../../../../common/endpoint/types';
|
||||
import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForCommandToBeExecuted,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../tasks/response_console';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../tasks/fleet';
|
||||
import {
|
||||
checkEndpointListForOnlyIsolatedHosts,
|
||||
checkEndpointListForOnlyUnIsolatedHosts,
|
||||
} from '../../tasks/isolate';
|
||||
import { checkEndpointListForOnlyUnIsolatedHosts } from '../../tasks/isolate';
|
||||
|
||||
import { login } from '../../tasks/login';
|
||||
import { enableAllPolicyProtections } from '../../tasks/endpoint_policy';
|
||||
|
@ -32,264 +27,9 @@ describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerles
|
|||
login();
|
||||
});
|
||||
|
||||
describe('User journey for Isolate command: isolate and release an endpoint', () => {
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('should isolate host from response console', () => {
|
||||
const command = 'isolate';
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyUnIsolatedHosts();
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks(command);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted(command);
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyIsolatedHosts();
|
||||
});
|
||||
|
||||
it('should release host from response console', () => {
|
||||
const command = 'release';
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyIsolatedHosts();
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks(command);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted(command);
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
checkEndpointListForOnlyUnIsolatedHosts();
|
||||
});
|
||||
});
|
||||
|
||||
describe('User journey for Processes operations: list, kill and suspend process', () => {
|
||||
let cronPID: string;
|
||||
let newCronPID: string;
|
||||
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('"processes" - should obtain a list of processes', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('processes');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => {
|
||||
['USER', 'PID', 'ENTITY ID', 'COMMAND'].forEach((header) => {
|
||||
cy.contains(header);
|
||||
});
|
||||
|
||||
cy.get('tbody > tr').should('have.length.greaterThan', 0);
|
||||
cy.get('tbody > tr > td').should('contain', '/usr/sbin/cron');
|
||||
cy.get('tbody > tr > td')
|
||||
.contains('/usr/sbin/cron')
|
||||
.parents('td')
|
||||
.siblings('td')
|
||||
.eq(1)
|
||||
.find('span')
|
||||
.then((span) => {
|
||||
cronPID = span.text();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('"kill-process --pid" - should kill a process', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`kill-process --pid ${cronPID}`);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('kill-process');
|
||||
|
||||
performCommandInputChecks('processes');
|
||||
submitCommand();
|
||||
|
||||
cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => {
|
||||
cy.get('tbody > tr > td')
|
||||
.contains('/usr/sbin/cron')
|
||||
.parents('td')
|
||||
.siblings('td')
|
||||
.eq(1)
|
||||
.find('span')
|
||||
.then((span) => {
|
||||
newCronPID = span.text();
|
||||
});
|
||||
});
|
||||
expect(newCronPID).to.not.equal(cronPID);
|
||||
});
|
||||
|
||||
it('"suspend-process --pid" - should suspend a process', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`suspend-process --pid ${newCronPID}`);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('suspend-process');
|
||||
});
|
||||
});
|
||||
|
||||
describe('File operations: get-file, upload and execute', () => {
|
||||
const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`;
|
||||
|
||||
const fileContent = 'This is a test file for the get-file command.';
|
||||
const filePath = `${homeFilePath}/test_file.txt`;
|
||||
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
||||
before(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
|
||||
return enableAllPolicyProtections(policy.id).then(() => {
|
||||
// Create and enroll a new Endpoint host
|
||||
return createEndpointHost(policy.policy_id).then((host) => {
|
||||
createdHost = host as CreateAndEnrollEndpointHostResponse;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (createdHost) {
|
||||
cy.task('destroyEndpointHost', createdHost);
|
||||
}
|
||||
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
|
||||
if (createdHost) {
|
||||
deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] });
|
||||
}
|
||||
});
|
||||
|
||||
it('"get-file --path" - should retrieve a file', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
cy.task('createFileOnEndpoint', {
|
||||
hostname: createdHost.hostname,
|
||||
path: filePath,
|
||||
content: fileContent,
|
||||
});
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`get-file --path ${filePath}`);
|
||||
submitCommand();
|
||||
cy.getByTestSubj('getFileSuccess', { timeout: 60000 }).within(() => {
|
||||
cy.contains('File retrieved from the host.');
|
||||
cy.contains('(ZIP file passcode: elastic)');
|
||||
cy.contains(
|
||||
'Files are periodically deleted to clear storage space. Download and save file locally if needed.'
|
||||
);
|
||||
cy.contains('Click here to download').click();
|
||||
const downloadsFolder = Cypress.config('downloadsFolder');
|
||||
cy.readFile(`${downloadsFolder}/upload.zip`);
|
||||
|
||||
cy.task('uploadFileToEndpoint', {
|
||||
hostname: createdHost.hostname,
|
||||
srcPath: `${downloadsFolder}/upload.zip`,
|
||||
destPath: `${homeFilePath}/upload.zip`,
|
||||
});
|
||||
|
||||
cy.task('readZippedFileContentOnEndpoint', {
|
||||
hostname: createdHost.hostname,
|
||||
path: `${homeFilePath}/upload.zip`,
|
||||
password: 'elastic',
|
||||
}).then((unzippedFileContent) => {
|
||||
expect(unzippedFileContent).to.equal(fileContent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('"execute --command" - should execute a command', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`execute --command "ls -al ${homeFilePath}"`);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('execute');
|
||||
});
|
||||
|
||||
it('"upload --file" - should upload a file', () => {
|
||||
waitForEndpointListPageToBeLoaded(createdHost.hostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`upload --file`);
|
||||
cy.getByTestSubj('console-arg-file-picker').selectFile(
|
||||
{
|
||||
contents: Cypress.Buffer.from('upload file content here!'),
|
||||
fileName: 'upload_file.txt',
|
||||
lastModified: Date.now(),
|
||||
},
|
||||
{ force: true }
|
||||
);
|
||||
submitCommand();
|
||||
waitForCommandToBeExecuted('upload');
|
||||
});
|
||||
});
|
||||
|
||||
describe('document signing', () => {
|
||||
// TODO: open PR https://github.com/elastic/kibana/pull/169539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/168296
|
||||
describe.skip('document signing', () => {
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
let createdHost: CreateAndEnrollEndpointHostResponse;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`execute` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let executeRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should execute a command from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`execute --command "ls -al"`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
executeRequestResponse = responseBody;
|
||||
}, 'execute');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@execute').then(() => {
|
||||
sendActionResponse(executeRequestResponse);
|
||||
});
|
||||
cy.contains('Command execution was successful', { timeout: 120000 }).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`get-file` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let getFileRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should get file from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`get-file --path /test/path/test.txt`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
getFileRequestResponse = responseBody;
|
||||
}, 'get-file');
|
||||
submitCommand();
|
||||
cy.contains('Retrieving the file from host.').should('exist');
|
||||
cy.wait('@get-file').then(() => {
|
||||
sendActionResponse(getFileRequestResponse);
|
||||
});
|
||||
cy.getByTestSubj('getFileSuccess').within(() => {
|
||||
cy.contains('File retrieved from the host.');
|
||||
cy.contains('(ZIP file passcode: elastic)');
|
||||
cy.contains(
|
||||
'Files are periodically deleted to clear storage space. Download and save file locally if needed.'
|
||||
);
|
||||
cy.contains('Click here to download').click();
|
||||
});
|
||||
|
||||
const downloadsFolder = Cypress.config('downloadsFolder');
|
||||
cy.readFile(`${downloadsFolder}/upload.zip`);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import {
|
||||
checkEndpointIsIsolated,
|
||||
checkEndpointIsNotIsolated,
|
||||
interceptActionRequests,
|
||||
sendActionResponse,
|
||||
} from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`isolate` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let isolateRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should isolate host from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsNotIsolated(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('isolate');
|
||||
interceptActionRequests((responseBody) => {
|
||||
isolateRequestResponse = responseBody;
|
||||
}, 'isolate');
|
||||
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@isolate').then(() => {
|
||||
sendActionResponse(isolateRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsIsolated(endpointHostname);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`kill-process` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let killProcessRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should kill process from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`kill-process --pid 1`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
killProcessRequestResponse = responseBody;
|
||||
}, 'kill-process');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@kill-process').then(() => {
|
||||
sendActionResponse(killProcessRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
checkReturnedProcessesTable,
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`processes` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let processesRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return processes from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('processes');
|
||||
interceptActionRequests((responseBody) => {
|
||||
processesRequestResponse = responseBody;
|
||||
}, 'processes');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@processes').then(() => {
|
||||
sendActionResponse(processesRequestResponse);
|
||||
});
|
||||
cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => {
|
||||
checkReturnedProcessesTable();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import {
|
||||
checkEndpointIsIsolated,
|
||||
checkEndpointIsNotIsolated,
|
||||
interceptActionRequests,
|
||||
sendActionResponse,
|
||||
} from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`release` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let releaseRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: true }).then((indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should release host from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsIsolated(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('release');
|
||||
interceptActionRequests((responseBody) => {
|
||||
releaseRequestResponse = responseBody;
|
||||
}, 'release');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@release').then(() => {
|
||||
sendActionResponse(releaseRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsNotIsolated(endpointHostname);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../../types';
|
||||
import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../../tasks/response_console';
|
||||
import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`suspend-process` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let suspendProcessRequestResponse: ActionDetails;
|
||||
|
||||
beforeEach(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should suspend process from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`suspend-process --pid 1`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
suspendProcessRequestResponse = responseBody;
|
||||
}, 'suspend-process');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@suspend-process').then(() => {
|
||||
sendActionResponse(suspendProcessRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,319 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ActionDetails } from '../../../../../common/endpoint/types';
|
||||
import type { ReturnTypeFromChainable } from '../../types';
|
||||
import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts';
|
||||
import {
|
||||
checkReturnedProcessesTable,
|
||||
inputConsoleCommand,
|
||||
openResponseConsoleFromEndpointList,
|
||||
performCommandInputChecks,
|
||||
submitCommand,
|
||||
waitForEndpointListPageToBeLoaded,
|
||||
} from '../../tasks/response_console';
|
||||
import {
|
||||
checkEndpointIsIsolated,
|
||||
checkEndpointIsNotIsolated,
|
||||
interceptActionRequests,
|
||||
sendActionResponse,
|
||||
} from '../../tasks/isolate';
|
||||
import { login } from '../../tasks/login';
|
||||
|
||||
describe('Response console', { tags: ['@ess', '@serverless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('`isolate` command', { tags: ['@brokenInServerless'] }, () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let isolateRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should isolate host from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsNotIsolated(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('isolate');
|
||||
interceptActionRequests((responseBody) => {
|
||||
isolateRequestResponse = responseBody;
|
||||
}, 'isolate');
|
||||
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@isolate').then(() => {
|
||||
sendActionResponse(isolateRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsIsolated(endpointHostname);
|
||||
});
|
||||
});
|
||||
|
||||
describe('`release` command', { tags: ['@brokenInServerless'] }, () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let releaseRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: true }).then((indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should release host from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsIsolated(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('release');
|
||||
interceptActionRequests((responseBody) => {
|
||||
releaseRequestResponse = responseBody;
|
||||
}, 'release');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@release').then(() => {
|
||||
sendActionResponse(releaseRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
checkEndpointIsNotIsolated(endpointHostname);
|
||||
});
|
||||
});
|
||||
|
||||
describe('`processes` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let processesRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return processes from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
performCommandInputChecks('processes');
|
||||
interceptActionRequests((responseBody) => {
|
||||
processesRequestResponse = responseBody;
|
||||
}, 'processes');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@processes').then(() => {
|
||||
sendActionResponse(processesRequestResponse);
|
||||
});
|
||||
cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => {
|
||||
checkReturnedProcessesTable();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('`kill-process` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let killProcessRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should kill process from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`kill-process --pid 1`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
killProcessRequestResponse = responseBody;
|
||||
}, 'kill-process');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@kill-process').then(() => {
|
||||
sendActionResponse(killProcessRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('`suspend-process` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let suspendProcessRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should suspend process from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`suspend-process --pid 1`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
suspendProcessRequestResponse = responseBody;
|
||||
}, 'suspend-process');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@suspend-process').then(() => {
|
||||
sendActionResponse(suspendProcessRequestResponse);
|
||||
});
|
||||
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
// Broken until this is fixed: https://github.com/elastic/kibana/issues/162760
|
||||
describe.skip('`get-file` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let getFileRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should get file from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`get-file --path /test/path/test.txt`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
getFileRequestResponse = responseBody;
|
||||
}, 'get-file');
|
||||
submitCommand();
|
||||
cy.contains('Retrieving the file from host.').should('exist');
|
||||
cy.wait('@get-file').then(() => {
|
||||
sendActionResponse(getFileRequestResponse);
|
||||
});
|
||||
cy.getByTestSubj('getFileSuccess').within(() => {
|
||||
cy.contains('File retrieved from the host.');
|
||||
cy.contains('(ZIP file passcode: elastic)');
|
||||
cy.contains(
|
||||
'Files are periodically deleted to clear storage space. Download and save file locally if needed.'
|
||||
);
|
||||
cy.contains('Click here to download').click();
|
||||
});
|
||||
|
||||
const downloadsFolder = Cypress.config('downloadsFolder');
|
||||
cy.readFile(`${downloadsFolder}/upload.zip`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('`execute` command', () => {
|
||||
let endpointData: ReturnTypeFromChainable<typeof indexEndpointHosts>;
|
||||
let endpointHostname: string;
|
||||
let executeRequestResponse: ActionDetails;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ withResponseActions: false, isolation: false }).then(
|
||||
(indexEndpoints) => {
|
||||
endpointData = indexEndpoints;
|
||||
endpointHostname = endpointData.data.hosts[0].host.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (endpointData) {
|
||||
endpointData.cleanup();
|
||||
// @ts-expect-error ignore setting to undefined
|
||||
endpointData = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('should execute a command from response console', () => {
|
||||
waitForEndpointListPageToBeLoaded(endpointHostname);
|
||||
openResponseConsoleFromEndpointList();
|
||||
inputConsoleCommand(`execute --command "ls -al"`);
|
||||
|
||||
interceptActionRequests((responseBody) => {
|
||||
executeRequestResponse = responseBody;
|
||||
}, 'execute');
|
||||
submitCommand();
|
||||
cy.contains('Action pending.').should('exist');
|
||||
cy.wait('@execute').then(() => {
|
||||
sendActionResponse(executeRequestResponse);
|
||||
});
|
||||
cy.contains('Command execution was successful', { timeout: 120000 }).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue