mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Defend Workflows] PoC of e2e endpoint testing (#148893)
This commit is contained in:
parent
168b9fd395
commit
e5895c30ba
22 changed files with 330 additions and 38 deletions
|
@ -26,6 +26,7 @@ disabled:
|
|||
- x-pack/test/functional_enterprise_search/cypress.config.ts
|
||||
- x-pack/test/defend_workflows_cypress/cli_config.ts
|
||||
- x-pack/test/defend_workflows_cypress/config.ts
|
||||
- x-pack/test/defend_workflows_cypress/endpoint_config.ts
|
||||
- x-pack/test/defend_workflows_cypress/visual_config.ts
|
||||
- x-pack/test/osquery_cypress/cli_config.ts
|
||||
- x-pack/test/osquery_cypress/config.ts
|
||||
|
|
|
@ -16,6 +16,7 @@ import type {
|
|||
DeleteAgentPolicyResponse,
|
||||
PostDeletePackagePoliciesResponse,
|
||||
} from '@kbn/fleet-plugin/common';
|
||||
import { kibanaPackageJson } from '@kbn/repo-info';
|
||||
import { AGENT_POLICY_API_ROUTES, PACKAGE_POLICY_API_ROUTES } from '@kbn/fleet-plugin/common';
|
||||
import type { PolicyData } from '../types';
|
||||
import { policyFactory as policyConfigFactory } from '../models/policy_config';
|
||||
|
@ -33,7 +34,7 @@ export interface IndexedFleetEndpointPolicyResponse {
|
|||
export const indexFleetEndpointPolicy = async (
|
||||
kbnClient: KbnClient,
|
||||
policyName: string,
|
||||
endpointPackageVersion: string = '8.0.0',
|
||||
endpointPackageVersion: string = kibanaPackageJson.version,
|
||||
agentPolicyName?: string
|
||||
): Promise<IndexedFleetEndpointPolicyResponse> => {
|
||||
const response: IndexedFleetEndpointPolicyResponse = {
|
||||
|
@ -47,6 +48,7 @@ export const indexFleetEndpointPolicy = async (
|
|||
agentPolicyName || `Policy for ${policyName} (${Math.random().toString(36).substr(2, 5)})`,
|
||||
description: `Policy created with endpoint data generator (${policyName})`,
|
||||
namespace: 'default',
|
||||
monitoring_enabled: ['logs', 'metrics'],
|
||||
};
|
||||
|
||||
let agentPolicy: AxiosResponse<CreateAgentPolicyResponse>;
|
||||
|
@ -86,7 +88,7 @@ export const indexFleetEndpointPolicy = async (
|
|||
namespace: 'default',
|
||||
package: {
|
||||
name: 'endpoint',
|
||||
title: 'endpoint',
|
||||
title: 'Elastic Defend',
|
||||
version: endpointPackageVersion,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
"cypress:dw:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/defend_workflows_cypress/visual_config.ts",
|
||||
"cypress:dw:run": "yarn cypress run --config-file ./public/management/cypress.config.ts",
|
||||
"cypress:dw:run-as-ci": "node ../../../scripts/functional_tests --config ../../test/defend_workflows_cypress/cli_config.ts",
|
||||
"cypress:dw:endpoint:open": "yarn cypress open --config-file ./public/management/cypress_endpoint.config.ts",
|
||||
"cypress:dw:endpoint:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/defend_workflows_cypress/endpoint_config.ts",
|
||||
"junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results && mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/",
|
||||
"test:generate": "node scripts/endpoint/resolver_generator"
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ export default defineCypressConfig({
|
|||
e2e: {
|
||||
baseUrl: 'http://localhost:5620',
|
||||
supportFile: 'public/management/cypress/support/e2e.ts',
|
||||
specPattern: 'public/management/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
|
||||
specPattern: 'public/management/cypress/e2e/mocked_data/*.cy.{js,jsx,ts,tsx}',
|
||||
experimentalRunAllSpecs: true,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { login } from '../../tasks/login';
|
||||
|
||||
describe('Endpoints page', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
it('Loads the endpoints page', () => {
|
||||
cy.visit('/app/security/administration/endpoints');
|
||||
cy.contains('Hosts running Elastic Defend').should('exist');
|
||||
});
|
||||
});
|
|
@ -5,18 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getEndpointSecurityPolicyManager } from '../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager';
|
||||
import { getArtifactsListTestsData } from '../fixtures/artifacts_page';
|
||||
import { getEndpointSecurityPolicyManager } from '../../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager';
|
||||
import { getArtifactsListTestsData } from '../../fixtures/artifacts_page';
|
||||
import {
|
||||
createPerPolicyArtifact,
|
||||
createArtifactList,
|
||||
removeAllArtifacts,
|
||||
removeExceptionsList,
|
||||
yieldFirstPolicyID,
|
||||
} from '../tasks/artifacts';
|
||||
import { loadEndpointDataForEventFiltersIfNeeded } from '../tasks/load_endpoint_data';
|
||||
import { login, loginWithCustomRole, loginWithRole, ROLE } from '../tasks/login';
|
||||
import { performUserActions } from '../tasks/perform_user_actions';
|
||||
} from '../../tasks/artifacts';
|
||||
import { loadEndpointDataForEventFiltersIfNeeded } from '../../tasks/load_endpoint_data';
|
||||
import { login, loginWithCustomRole, loginWithRole, ROLE } from '../../tasks/login';
|
||||
import { performUserActions } from '../../tasks/perform_user_actions';
|
||||
|
||||
const loginWithPrivilegeAll = () => {
|
||||
loginWithRole(ROLE.endpoint_security_policy_manager);
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { login, loginWithRole, ROLE } from '../tasks/login';
|
||||
import { login, loginWithRole, ROLE } from '../../tasks/login';
|
||||
|
||||
import { getArtifactsListTestsData } from '../fixtures/artifacts_page';
|
||||
import { removeAllArtifacts } from '../tasks/artifacts';
|
||||
import { performUserActions } from '../tasks/perform_user_actions';
|
||||
import { loadEndpointDataForEventFiltersIfNeeded } from '../tasks/load_endpoint_data';
|
||||
import { getArtifactsListTestsData } from '../../fixtures/artifacts_page';
|
||||
import { removeAllArtifacts } from '../../tasks/artifacts';
|
||||
import { performUserActions } from '../../tasks/perform_user_actions';
|
||||
import { loadEndpointDataForEventFiltersIfNeeded } from '../../tasks/load_endpoint_data';
|
||||
|
||||
const loginWithWriteAccess = (url: string) => {
|
||||
loginWithRole(ROLE.analyst_hunter);
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { login } from '../tasks/login';
|
||||
import { runEndpointLoaderScript } from '../tasks/run_endpoint_loader';
|
||||
import { login } from '../../tasks/login';
|
||||
import { runEndpointLoaderScript } from '../../tasks/run_endpoint_loader';
|
||||
|
||||
describe('Endpoints page', () => {
|
||||
before(() => {
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default defineCypressConfig({
|
||||
defaultCommandTimeout: 60000,
|
||||
execTimeout: 120000,
|
||||
pageLoadTimeout: 12000,
|
||||
|
||||
retries: {
|
||||
runMode: 1,
|
||||
openMode: 0,
|
||||
},
|
||||
|
||||
screenshotsFolder:
|
||||
'../../../target/kibana-security-solution/public/management/cypress/screenshots',
|
||||
trashAssetsBeforeRuns: false,
|
||||
video: false,
|
||||
viewportHeight: 900,
|
||||
viewportWidth: 1440,
|
||||
experimentalStudio: true,
|
||||
|
||||
env: {
|
||||
'cypress-react-selector': {
|
||||
root: '#security-solution-app',
|
||||
},
|
||||
},
|
||||
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:5620',
|
||||
supportFile: 'public/management/cypress/support/e2e.ts',
|
||||
specPattern: 'public/management/cypress/e2e/endpoint/*.cy.{js,jsx,ts,tsx}',
|
||||
experimentalRunAllSpecs: true,
|
||||
},
|
||||
});
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { pick } from 'lodash';
|
||||
import type { Client, estypes } from '@elastic/elasticsearch';
|
||||
import type {
|
||||
Agent,
|
||||
|
@ -14,7 +15,6 @@ import type {
|
|||
GetAgentsResponse,
|
||||
} from '@kbn/fleet-plugin/common';
|
||||
import { AGENT_API_ROUTES, agentPolicyRouteService, AGENTS_INDEX } from '@kbn/fleet-plugin/common';
|
||||
import { pick } from 'lodash';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import type { KbnClient } from '@kbn/test';
|
||||
import type { GetFleetServerHostsResponse } from '@kbn/fleet-plugin/common/types/rest_spec/fleet_server_hosts';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import execa from 'execa';
|
||||
import { networkInterfaces } from 'node:os';
|
||||
|
||||
const POSSIBLE_LOCALHOST_VALUES: readonly string[] = [
|
||||
'localhost',
|
||||
|
@ -15,13 +15,21 @@ const POSSIBLE_LOCALHOST_VALUES: readonly string[] = [
|
|||
'0000:0000:0000:0000:0000:0000:0000:0000',
|
||||
];
|
||||
|
||||
export const getLocalhostRealIp = async (): Promise<string> => {
|
||||
// TODO:PT find better way to get host machine public IP. Command below is not x-platform
|
||||
|
||||
return execa.commandSync(
|
||||
"ipconfig getifaddr `scutil --dns |awk -F'[()]' '$1~/if_index/ {print $2;exit;}'`",
|
||||
{ shell: true }
|
||||
).stdout;
|
||||
export const getLocalhostRealIp = (): string => {
|
||||
for (const netInterfaceList of Object.values(networkInterfaces())) {
|
||||
if (netInterfaceList) {
|
||||
const netInterface = netInterfaceList.find(
|
||||
(networkInterface) =>
|
||||
networkInterface.family === 'IPv4' &&
|
||||
networkInterface.internal === false &&
|
||||
networkInterface.address
|
||||
);
|
||||
if (netInterface) {
|
||||
return netInterface.address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return '0.0.0.0';
|
||||
};
|
||||
|
||||
export const isLocalhost = (hostname: string): boolean => {
|
||||
|
|
|
@ -44,7 +44,8 @@ interface ElasticArtifactSearchResponse {
|
|||
};
|
||||
}
|
||||
|
||||
export const enrollEndpointHost = async () => {
|
||||
export const enrollEndpointHost = async (): Promise<string | undefined> => {
|
||||
let vmName;
|
||||
const {
|
||||
log,
|
||||
kbnClient,
|
||||
|
@ -80,7 +81,7 @@ export const enrollEndpointHost = async () => {
|
|||
throw new Error(`No API enrollment key found for policy id [${policyId}]`);
|
||||
}
|
||||
|
||||
const vmName = `${username}-dev-${uniqueId}`;
|
||||
vmName = `${username}-dev-${uniqueId}`;
|
||||
|
||||
log.info(`Creating VM named: ${vmName}`);
|
||||
|
||||
|
@ -166,6 +167,8 @@ export const enrollEndpointHost = async () => {
|
|||
}
|
||||
|
||||
log.indent(-4);
|
||||
|
||||
return vmName;
|
||||
};
|
||||
|
||||
const getAgentDownloadUrl = async (version: string): Promise<string> => {
|
||||
|
|
|
@ -44,7 +44,8 @@ import {
|
|||
} from '../common/fleet_services';
|
||||
import { getRuntimeServices } from './runtime';
|
||||
|
||||
export const runFleetServerIfNeeded = async () => {
|
||||
export const runFleetServerIfNeeded = async (): Promise<string | undefined> => {
|
||||
let fleetServerContainerId;
|
||||
const {
|
||||
log,
|
||||
kibana: { isLocalhost: isKibanaOnLocalhost },
|
||||
|
@ -69,7 +70,7 @@ export const runFleetServerIfNeeded = async () => {
|
|||
await configureFleetIfNeeded();
|
||||
}
|
||||
|
||||
await startFleetServerWithDocker({
|
||||
fleetServerContainerId = await startFleetServerWithDocker({
|
||||
policyId: fleetServerAgentPolicyId,
|
||||
serviceToken,
|
||||
});
|
||||
|
@ -80,6 +81,8 @@ export const runFleetServerIfNeeded = async () => {
|
|||
}
|
||||
|
||||
log.indent(-4);
|
||||
|
||||
return fleetServerContainerId;
|
||||
};
|
||||
|
||||
const isFleetServerEnrolled = async () => {
|
||||
|
@ -178,13 +181,14 @@ const generateFleetServiceToken = async (): Promise<string> => {
|
|||
return serviceToken;
|
||||
};
|
||||
|
||||
const startFleetServerWithDocker = async ({
|
||||
export const startFleetServerWithDocker = async ({
|
||||
policyId,
|
||||
serviceToken,
|
||||
}: {
|
||||
policyId: string;
|
||||
serviceToken: string;
|
||||
}) => {
|
||||
let containerId;
|
||||
const {
|
||||
log,
|
||||
localhostRealIp,
|
||||
|
@ -256,16 +260,16 @@ const startFleetServerWithDocker = async ({
|
|||
(This is ok if one was not running already)`);
|
||||
});
|
||||
|
||||
await addFleetServerHostToFleetSettings(`https://${localhostRealIp}:8220`);
|
||||
|
||||
log.verbose(`docker arguments:\n${dockerArgs.join(' ')}`);
|
||||
|
||||
const containerId = (await execa('docker', dockerArgs)).stdout;
|
||||
containerId = (await execa('docker', dockerArgs)).stdout;
|
||||
|
||||
const fleetServerAgent = await waitForHostToEnroll(kbnClient, containerName);
|
||||
|
||||
log.verbose(`Fleet server enrolled agent:\n${JSON.stringify(fleetServerAgent, null, 2)}`);
|
||||
|
||||
await addFleetServerHostToFleetSettings(`https://${localhostRealIp}:8220`);
|
||||
|
||||
log.info(`Done. Fleet Server is running and connected to Fleet.
|
||||
Container Name: ${containerName}
|
||||
Container Id: ${containerId}
|
||||
|
@ -280,6 +284,8 @@ const startFleetServerWithDocker = async ({
|
|||
}
|
||||
|
||||
log.indent(-4);
|
||||
|
||||
return containerId;
|
||||
};
|
||||
|
||||
const configureFleetIfNeeded = async () => {
|
||||
|
|
|
@ -12,8 +12,9 @@ import type { RuntimeServices } from '../common/stack_services';
|
|||
import { createRuntimeServices } from '../common/stack_services';
|
||||
|
||||
interface EndpointRunnerRuntimeServices extends RuntimeServices {
|
||||
options: Required<
|
||||
Omit<StartRuntimeServicesOptions, 'kibanaUrl' | 'elasticUrl' | 'username' | 'password' | 'log'>
|
||||
options: Omit<
|
||||
StartRuntimeServicesOptions,
|
||||
'kibanaUrl' | 'elasticUrl' | 'username' | 'password' | 'log'
|
||||
>;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ export interface StartRuntimeServicesOptions {
|
|||
elasticUrl: string;
|
||||
username: string;
|
||||
password: string;
|
||||
version: string;
|
||||
policy: string;
|
||||
version?: string;
|
||||
policy?: string;
|
||||
log?: ToolingLog;
|
||||
}
|
||||
|
|
35
x-pack/test/defend_workflows_cypress/agent.ts
Normal file
35
x-pack/test/defend_workflows_cypress/agent.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 execa from 'execa';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { enrollEndpointHost } from '@kbn/security-solution-plugin/scripts/endpoint/endpoint_agent_runner/elastic_endpoint';
|
||||
import { Manager } from './resource_manager';
|
||||
|
||||
export class AgentManager extends Manager {
|
||||
private log: ToolingLog;
|
||||
private vmName?: string;
|
||||
constructor(log: ToolingLog) {
|
||||
super();
|
||||
this.log = log;
|
||||
this.vmName = undefined;
|
||||
}
|
||||
|
||||
public async setup() {
|
||||
this.vmName = await enrollEndpointHost();
|
||||
}
|
||||
|
||||
public cleanup() {
|
||||
super.cleanup();
|
||||
this.log.info('Cleaning up the agent process');
|
||||
if (this.vmName) {
|
||||
execa.commandSync(`multipass delete -p ${this.vmName}`);
|
||||
|
||||
this.log.info('Agent process closed');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { CA_CERT_PATH } from '@kbn/dev-utils';
|
||||
import { getLocalhostRealIp } from '@kbn/security-solution-plugin/scripts/endpoint/common/localhost_services';
|
||||
import { services } from './services';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
|
@ -17,6 +18,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
require.resolve('../functional/config.base.js')
|
||||
);
|
||||
|
||||
const hostIp = getLocalhostRealIp();
|
||||
|
||||
return {
|
||||
...kibanaCommonTestsConfig.getAll(),
|
||||
|
||||
|
@ -41,6 +44,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
'--csp.strict=false',
|
||||
// define custom kibana server args here
|
||||
`--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,
|
||||
`--xpack.fleet.agents.fleet_server.hosts=["https://${hostIp}:8220"]`,
|
||||
`--xpack.fleet.agents.elasticsearch.host=http://${hostIp}:${kibanaCommonTestsConfig.get(
|
||||
'servers.elasticsearch.port'
|
||||
)}`,
|
||||
// always install Endpoint package by default when Fleet sets up
|
||||
`--xpack.fleet.packages.0.name=endpoint`,
|
||||
`--xpack.fleet.packages.0.version=latest`,
|
||||
|
|
32
x-pack/test/defend_workflows_cypress/endpoint_config.ts
Normal file
32
x-pack/test/defend_workflows_cypress/endpoint_config.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 { getLocalhostRealIp } from '@kbn/security-solution-plugin/scripts/endpoint/common/localhost_services';
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
import { DefendWorkflowsCypressEndpointTestRunner } from './runner';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const defendWorkflowsCypressConfig = await readConfigFile(require.resolve('./config.ts'));
|
||||
const config = defendWorkflowsCypressConfig.getAll();
|
||||
const hostIp = getLocalhostRealIp();
|
||||
|
||||
return {
|
||||
...config,
|
||||
kbnTestServer: {
|
||||
...config.kbnTestServer,
|
||||
serverArgs: [
|
||||
...config.kbnTestServer.serverArgs,
|
||||
`--xpack.fleet.agents.fleet_server.hosts=["https://${hostIp}:8220"]`,
|
||||
`--xpack.fleet.agents.elasticsearch.host=http://${hostIp}:${defendWorkflowsCypressConfig.get(
|
||||
'servers.elasticsearch.port'
|
||||
)}`,
|
||||
],
|
||||
},
|
||||
testRunner: DefendWorkflowsCypressEndpointTestRunner,
|
||||
};
|
||||
}
|
37
x-pack/test/defend_workflows_cypress/fleet_server.ts
Normal file
37
x-pack/test/defend_workflows_cypress/fleet_server.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 execa from 'execa';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { runFleetServerIfNeeded } from '@kbn/security-solution-plugin/scripts/endpoint/endpoint_agent_runner/fleet_server';
|
||||
import { Manager } from './resource_manager';
|
||||
|
||||
export class FleetManager extends Manager {
|
||||
private fleetContainerId?: string;
|
||||
private log: ToolingLog;
|
||||
|
||||
constructor(log: ToolingLog) {
|
||||
super();
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public async setup(): Promise<void> {
|
||||
this.fleetContainerId = await runFleetServerIfNeeded();
|
||||
}
|
||||
|
||||
public cleanup() {
|
||||
super.cleanup();
|
||||
|
||||
this.log.info('Removing old fleet config');
|
||||
if (this.fleetContainerId) {
|
||||
this.log.info('Closing fleet process');
|
||||
|
||||
execa.sync('docker', ['kill', this.fleetContainerId]);
|
||||
this.log.info('Fleet server process closed');
|
||||
}
|
||||
}
|
||||
}
|
15
x-pack/test/defend_workflows_cypress/resource_manager.ts
Normal file
15
x-pack/test/defend_workflows_cypress/resource_manager.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const CLEANUP_EVENTS = ['SIGINT', 'exit', 'uncaughtException', 'unhandledRejection'];
|
||||
export class Manager {
|
||||
constructor() {
|
||||
const cleanup = () => this.cleanup();
|
||||
CLEANUP_EVENTS.forEach((ev) => process.on(ev, cleanup));
|
||||
}
|
||||
cleanup() {}
|
||||
}
|
|
@ -8,8 +8,46 @@
|
|||
import { resolve } from 'path';
|
||||
import Url from 'url';
|
||||
import { withProcRunner } from '@kbn/dev-proc-runner';
|
||||
|
||||
import { startRuntimeServices } from '@kbn/security-solution-plugin/scripts/endpoint/endpoint_agent_runner/runtime';
|
||||
import { FtrProviderContext } from './ftr_provider_context';
|
||||
import { AgentManager } from './agent';
|
||||
import { FleetManager } from './fleet_server';
|
||||
import { getLatestAvailableAgentVersion } from './utils';
|
||||
|
||||
async function withFleetAgent(
|
||||
{ getService }: FtrProviderContext,
|
||||
runner: (runnerEnv: Record<string, string>) => Promise<void>
|
||||
) {
|
||||
const log = getService('log');
|
||||
const config = getService('config');
|
||||
const kbnClient = getService('kibanaServer');
|
||||
|
||||
const elasticUrl = Url.format(config.get('servers.elasticsearch'));
|
||||
const kibanaUrl = Url.format(config.get('servers.kibana'));
|
||||
const username = config.get('servers.elasticsearch.username');
|
||||
const password = config.get('servers.elasticsearch.password');
|
||||
|
||||
await startRuntimeServices({
|
||||
log,
|
||||
elasticUrl,
|
||||
kibanaUrl,
|
||||
username,
|
||||
password,
|
||||
version: await getLatestAvailableAgentVersion(kbnClient),
|
||||
});
|
||||
|
||||
const fleetManager = new FleetManager(log);
|
||||
const agentManager = new AgentManager(log);
|
||||
|
||||
await fleetManager.setup();
|
||||
await agentManager.setup();
|
||||
try {
|
||||
await runner({});
|
||||
} finally {
|
||||
agentManager.cleanup();
|
||||
fleetManager.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
export async function DefendWorkflowsCypressCliTestRunner(context: FtrProviderContext) {
|
||||
await startDefendWorkflowsCypress(context, 'dw:run');
|
||||
|
@ -19,6 +57,10 @@ export async function DefendWorkflowsCypressVisualTestRunner(context: FtrProvide
|
|||
await startDefendWorkflowsCypress(context, 'dw:open');
|
||||
}
|
||||
|
||||
export async function DefendWorkflowsCypressEndpointTestRunner(context: FtrProviderContext) {
|
||||
await withFleetAgent(context, () => startDefendWorkflowsCypress(context, 'dw:endpoint:open'));
|
||||
}
|
||||
|
||||
function startDefendWorkflowsCypress(context: FtrProviderContext, cypressCommand: string) {
|
||||
const log = context.getService('log');
|
||||
const config = context.getService('config');
|
||||
|
|
41
x-pack/test/defend_workflows_cypress/utils.ts
Normal file
41
x-pack/test/defend_workflows_cypress/utils.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 axios from 'axios';
|
||||
import semver from 'semver';
|
||||
import { filter } from 'lodash';
|
||||
import { KbnClient } from '@kbn/test';
|
||||
|
||||
/**
|
||||
* Returns the Agent version that is available for install (will check `artifacts-api.elastic.co/v1/versions`)
|
||||
* that is equal to or less than `maxVersion`.
|
||||
* @param maxVersion
|
||||
*/
|
||||
|
||||
export const getLatestAvailableAgentVersion = async (kbnClient: KbnClient): Promise<string> => {
|
||||
const kbnStatus = await kbnClient.status.get();
|
||||
const agentVersions = await axios
|
||||
.get('https://artifacts-api.elastic.co/v1/versions')
|
||||
.then((response) =>
|
||||
filter(response.data.versions, (versionString) => !versionString.includes('SNAPSHOT'))
|
||||
);
|
||||
|
||||
let version =
|
||||
semver.maxSatisfying(agentVersions, `<=${kbnStatus.version.number}`) ??
|
||||
kbnStatus.version.number;
|
||||
|
||||
// Add `-SNAPSHOT` if version indicates it was from a snapshot or the build hash starts
|
||||
// with `xxxxxxxxx` (value that seems to be present when running kibana from source)
|
||||
if (
|
||||
kbnStatus.version.build_snapshot ||
|
||||
kbnStatus.version.build_hash.startsWith('XXXXXXXXXXXXXXX')
|
||||
) {
|
||||
version += '-SNAPSHOT';
|
||||
}
|
||||
|
||||
return version;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue