mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 19:13:14 -04:00
This PR introduces osquery Cypress tests to the MKI environment. These tests will be executed within the **Kibana / Serverless / Security Solution Quality Gate / Defend Workflows** scope. You can find an example of the build here: [Buildkite Example](https://buildkite.com/elastic/kibana-serverless-security-solution-quality-gate-defend-workflows/builds/1049). The main challenge with running osquery tests in MKI is that we cannot continuously log in users as we do in other environments. This is due to an issue where users are logged out when switching apps. To address this, I've added a simple check in the login method to prevent the login function from being called unnecessarily in MKI. This is a temporary solution until we can properly log in users via API calls using authentication tokens. All the `chalk` & `log.indent` changes were made to make logs more beautiful 😸  --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
173 lines
5 KiB
TypeScript
173 lines
5 KiB
TypeScript
/*
|
|
* 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 { map } from 'lodash';
|
|
import { PackagePolicy, CreatePackagePolicyResponse, API_VERSIONS } from '@kbn/fleet-plugin/common';
|
|
import { KbnClient } from '@kbn/test';
|
|
import {
|
|
GetEnrollmentAPIKeysResponse,
|
|
CreateAgentPolicyResponse,
|
|
} from '@kbn/fleet-plugin/common/types';
|
|
import { ToolingLog } from '@kbn/tooling-log';
|
|
import chalk from 'chalk';
|
|
|
|
export const DEFAULT_HEADERS = Object.freeze({
|
|
'x-elastic-internal-product': 'security-solution',
|
|
});
|
|
|
|
export const getInstalledIntegration = async (kbnClient: KbnClient, integrationName: string) => {
|
|
const {
|
|
data: { item },
|
|
} = await kbnClient.request<{ item: PackagePolicy }>({
|
|
method: 'GET',
|
|
path: `/api/fleet/epm/packages/${integrationName}`,
|
|
headers: {
|
|
...DEFAULT_HEADERS,
|
|
'elastic-api-version': API_VERSIONS.public.v1,
|
|
},
|
|
});
|
|
|
|
return item;
|
|
};
|
|
|
|
export const createAgentPolicy = async (
|
|
kbnClient: KbnClient,
|
|
log: ToolingLog,
|
|
agentPolicyName = 'Osquery policy',
|
|
integrationName: string = 'osquery_manager'
|
|
) => {
|
|
log.info(chalk.bold(`Creating "${agentPolicyName}" agent policy`));
|
|
const {
|
|
data: {
|
|
item: { id: agentPolicyId },
|
|
},
|
|
} = await kbnClient.request<CreateAgentPolicyResponse>({
|
|
method: 'POST',
|
|
path: `/api/fleet/agent_policies?sys_monitoring=true`,
|
|
headers: {
|
|
'elastic-api-version': API_VERSIONS.public.v1,
|
|
},
|
|
body: {
|
|
name: agentPolicyName,
|
|
description: '',
|
|
namespace: 'default',
|
|
monitoring_enabled: ['logs', 'metrics'],
|
|
inactivity_timeout: 1209600,
|
|
},
|
|
});
|
|
log.indent(4, () => log.info(`Created "${agentPolicyName}" agent policy`));
|
|
|
|
log.info(
|
|
chalk.bold(
|
|
`Adding "${integrationName}" integration to agent policy "${agentPolicyName}" with id ${agentPolicyId}`
|
|
)
|
|
);
|
|
|
|
await addIntegrationToAgentPolicy(kbnClient, agentPolicyId, agentPolicyName, integrationName);
|
|
log.indent(4, () =>
|
|
log.info(
|
|
`Added "${integrationName}" integration to agent policy "${agentPolicyName}" with id ${agentPolicyId}`
|
|
)
|
|
);
|
|
|
|
log.info(
|
|
chalk.bold(
|
|
`Getting agent enrollment key for agent policy "${agentPolicyName}" with id ${agentPolicyId}`
|
|
)
|
|
);
|
|
const { data: apiKeys } = await kbnClient.request<GetEnrollmentAPIKeysResponse>({
|
|
method: 'GET',
|
|
headers: {
|
|
'elastic-api-version': API_VERSIONS.public.v1,
|
|
},
|
|
path: '/api/fleet/enrollment_api_keys',
|
|
});
|
|
log.indent(4, () =>
|
|
log.info(
|
|
`Got agent enrollment key for agent policy "${agentPolicyName}" with id ${agentPolicyId}`
|
|
)
|
|
);
|
|
return apiKeys.items[0].api_key;
|
|
};
|
|
|
|
export const addIntegrationToAgentPolicy = async (
|
|
kbnClient: KbnClient,
|
|
agentPolicyId: string,
|
|
agentPolicyName: string,
|
|
integrationName: string = 'osquery_manager'
|
|
) => {
|
|
const { version: integrationVersion } = await getInstalledIntegration(kbnClient, integrationName);
|
|
|
|
return kbnClient.request<CreatePackagePolicyResponse>({
|
|
method: 'POST',
|
|
path: '/api/fleet/package_policies',
|
|
headers: {
|
|
'elastic-api-version': API_VERSIONS.public.v1,
|
|
},
|
|
body: {
|
|
policy_id: agentPolicyId,
|
|
package: {
|
|
name: integrationName,
|
|
version: integrationVersion,
|
|
},
|
|
name: `Policy for ${agentPolicyName}`,
|
|
description: '',
|
|
namespace: 'default',
|
|
inputs: {
|
|
'osquery_manager-osquery': {
|
|
enabled: true,
|
|
streams: {},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Check if the given version string is a valid artifact version
|
|
* @param version Version string
|
|
*/
|
|
const isValidArtifactVersion = (version: string) => !!version.match(/^\d+\.\d+\.\d+(-SNAPSHOT)?$/);
|
|
|
|
/**
|
|
* 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 kbnClient
|
|
*/
|
|
|
|
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) =>
|
|
map(
|
|
response.data.versions.filter(isValidArtifactVersion),
|
|
(version) => version.split('-SNAPSHOT')[0]
|
|
)
|
|
);
|
|
|
|
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;
|
|
};
|
|
|
|
export const generateRandomString = (length: number) => {
|
|
return [...Array(length)].map(() => Math.random().toString(36)[2]).join('');
|
|
};
|