[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:
Ash 2023-11-01 12:59:23 +01:00 committed by GitHub
parent 0b6e79eb33
commit 1015325669
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 886 additions and 585 deletions

View file

@ -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,

View file

@ -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');
});
});
});

View file

@ -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');
});
});
});

View file

@ -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();
});
});
});

View file

@ -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');
});
});
});

View file

@ -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;

View file

@ -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');
});
});
});

View file

@ -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`);
});
});
});

View file

@ -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);
});
});
});

View file

@ -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');
});
});
});

View file

@ -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();
});
});
});
});

View file

@ -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);
});
});
});

View file

@ -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');
});
});
});

View file

@ -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');
});
});
});