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

This PR tackles `get-file` command issued from response console. Two
tests are included:
1.
`x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts`
mocked data
2.
`x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts`
real endpoint

---------

Co-authored-by: Patryk Kopycinski <contact@patrykkopycinski.com>
This commit is contained in:
Konrad Szwarc 2023-05-16 19:55:57 +02:00 committed by GitHub
parent 82108060e7
commit cf6f350ed2
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

@ -8,6 +8,7 @@
// / <reference types="cypress" />
import type { CasePostRequest } from '@kbn/cases-plugin/common/api';
import execa from 'execa';
import {
sendEndpointActionResponse,
sendFleetActionResponse,
@ -224,6 +225,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;