[8.8] [Defend Workflows][E2E]Get file command from response console (#156159) (#158542)

# Backport

This will backport the following commits from `main` to `8.8`:
- [[Defend Workflows][E2E]Get file command from response console
(#156159)](https://github.com/elastic/kibana/pull/156159)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Konrad
Szwarc","email":"konrad.szwarc@elastic.co"},"sourceCommit":{"committedDate":"2023-05-16T17:55:57Z","message":"[Defend
Workflows][E2E]Get file command from response console (#156159)\n\nThis
PR tackles `get-file` command issued from response console. Two\r\ntests
are
included:\r\n1.\r\n`x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts`\r\nmocked
data\r\n2.\r\n`x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts`\r\nreal
endpoint\r\n\r\n---------\r\n\r\nCo-authored-by: Patryk Kopycinski
<contact@patrykkopycinski.com>","sha":"cf6f350ed21eb86053e54005a5d59b1ff64a2d0d","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Defend
Workflows","v8.8.0","v8.9.0"],"number":156159,"url":"https://github.com/elastic/kibana/pull/156159","mergeCommit":{"message":"[Defend
Workflows][E2E]Get file command from response console (#156159)\n\nThis
PR tackles `get-file` command issued from response console. Two\r\ntests
are
included:\r\n1.\r\n`x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts`\r\nmocked
data\r\n2.\r\n`x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts`\r\nreal
endpoint\r\n\r\n---------\r\n\r\nCo-authored-by: Patryk Kopycinski
<contact@patrykkopycinski.com>","sha":"cf6f350ed21eb86053e54005a5d59b1ff64a2d0d"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/156159","number":156159,"mergeCommit":{"message":"[Defend
Workflows][E2E]Get file command from response console (#156159)\n\nThis
PR tackles `get-file` command issued from response console. Two\r\ntests
are
included:\r\n1.\r\n`x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts`\r\nmocked
data\r\n2.\r\n`x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts`\r\nreal
endpoint\r\n\r\n---------\r\n\r\nCo-authored-by: Patryk Kopycinski
<contact@patrykkopycinski.com>","sha":"cf6f350ed21eb86053e54005a5d59b1ff64a2d0d"}}]}]
BACKPORT-->

Co-authored-by: Ashokaditya <1849116+ashokaditya@users.noreply.github.com>
This commit is contained in:
Konrad Szwarc 2023-05-26 22:39:28 +02:00 committed by GitHub
parent a47810d7c8
commit f97c2cc0cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 206 additions and 0 deletions

View file

@ -145,6 +145,30 @@ declare global {
arg: { endpointAgentIds: string[] },
options?: Partial<Loggable & Timeoutable>
): Chainable<DeleteAllEndpointDataResponse>;
task(
name: 'createFileOnEndpoint',
arg: { hostname: string; path: string; content: string },
options?: Partial<Loggable & Timeoutable>
): Chainable<null>;
task(
name: 'uploadFileToEndpoint',
arg: { hostname: string; srcPath: string; destPath: string },
options?: Partial<Loggable & Timeoutable>
): Chainable<null>;
task(
name: 'installPackagesOnEndpoint',
arg: { hostname: string; packages: string[] },
options?: Partial<Loggable & Timeoutable>
): Chainable<null>;
task(
name: 'readZippedFileContentOnEndpoint',
arg: { hostname: string; path: string; password?: string },
options?: Partial<Loggable & Timeoutable>
): Chainable<string>;
}
}
}

View file

@ -168,6 +168,74 @@ describe('Response console', () => {
});
});
describe('User journey for Get file command', () => {
let response: IndexedFleetEndpointPolicyResponse;
let initialAgentData: Agent;
const fileContent = 'This is a test file for the get-file command.';
const filePath = `/home/ubuntu/test_file.txt`;
before(() => {
getAgentByHostName(endpointHostname).then((agentData) => {
initialAgentData = agentData;
});
getEndpointIntegrationVersion().then((version) =>
createAgentPolicyTask(version).then((data) => {
response = data;
})
);
cy.task('installPackagesOnEndpoint', { hostname: endpointHostname, packages: ['unzip'] });
cy.task('createFileOnEndpoint', {
hostname: endpointHostname,
path: filePath,
content: fileContent,
});
});
after(() => {
if (initialAgentData?.policy_id) {
reassignAgentPolicy(initialAgentData.id, initialAgentData.policy_id);
}
if (response) {
cy.task('deleteIndexedFleetEndpointPolicies', response);
}
});
it('"get-file --path" - should retrieve a file', () => {
waitForEndpointListPageToBeLoaded(endpointHostname);
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: endpointHostname,
srcPath: `${downloadsFolder}/upload.zip`,
destPath: '/home/ubuntu/upload.zip',
});
cy.task('readZippedFileContentOnEndpoint', {
hostname: endpointHostname,
path: '/home/ubuntu/upload.zip',
password: 'elastic',
}).then((unzippedFileContent) => {
expect(unzippedFileContent).to.equal(fileContent);
});
});
});
});
describe('document signing', () => {
let response: IndexedFleetEndpointPolicyResponse;
let initialAgentData: Agent;

View file

@ -227,4 +227,53 @@ describe('Response console', () => {
cy.contains('Action completed.', { timeout: 120000 }).should('exist');
});
});
describe('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`);
});
});
});

View file

@ -7,6 +7,7 @@
// / <reference types="cypress" />
import execa from 'execa';
import type { CasePostRequest } from '@kbn/cases-plugin/common/api';
import {
sendEndpointActionResponse,
@ -227,6 +228,70 @@ export const dataLoadersForRealEndpoints = (
return destroyEndpointHost(kbnClient, createdHost).then(() => null);
},
createFileOnEndpoint: async ({
hostname,
path,
content,
}: {
hostname: string;
path: string;
content: string;
}): Promise<null> => {
await execa(`multipass`, ['exec', hostname, '--', 'sh', '-c', `echo ${content} > ${path}`]);
return null;
},
uploadFileToEndpoint: async ({
hostname,
srcPath,
destPath = '.',
}: {
hostname: string;
srcPath: string;
destPath: string;
}): Promise<null> => {
await execa(`multipass`, ['transfer', srcPath, `${hostname}:${destPath}`]);
return null;
},
installPackagesOnEndpoint: async ({
hostname,
packages,
}: {
hostname: string;
packages: string[];
}): Promise<null> => {
await execa(`multipass`, [
'exec',
hostname,
'--',
'sh',
'-c',
`sudo apt install -y ${packages.join(' ')}`,
]);
return null;
},
readZippedFileContentOnEndpoint: async ({
hostname,
path,
password,
}: {
hostname: string;
path: string;
password?: string;
}): Promise<string> => {
const result = await execa(`multipass`, [
'exec',
hostname,
'--',
'sh',
'-c',
`unzip -p ${password ? `-P ${password} ` : ''}${path}`,
]);
return result.stdout;
},
stopEndpointHost: async () => {
const hosts = await getEndpointHosts();
const hostName = hosts[0].name;