Skip to content

Commit

Permalink
Add creation of the connector + SIEM rule
Browse files Browse the repository at this point in the history
  • Loading branch information
paul-tavares committed Dec 19, 2024
1 parent 8037ec2 commit 22c09e0
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ const runCli: RunFn = async ({ log, flags }) => {

const activeSpaceId = (await fetchActiveSpace(kbnClient)).id;

await onboardVmHostWithMicrosoftDefender({ kbnClient, log });
await onboardVmHostWithMicrosoftDefender({ kbnClient, log, vmName, forceNewHost });

const {
id: agentPolicyId,
Expand Down Expand Up @@ -199,8 +199,17 @@ const runCli: RunFn = async ({ log, flags }) => {
}

await Promise.all([
createMicrosoftDefenderForEndpointConnectorIfNeeded(),
createDetectionEngineMicrosoftDefenderRuleIfNeeded(),
createMicrosoftDefenderForEndpointConnectorIfNeeded({
kbnClient,
log,
tenantId,
clientId,
clientSecret,
oAuthServerUrl,
oAuthScope,
apiUrl,
}),
createDetectionEngineMicrosoftDefenderRuleIfNeeded(kbnClient, log, agentPolicyNamespace),
]);

// FIXME:PT trigger alert in VM whenever that is implemented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,48 @@
* 2.0.
*/

export const createDetectionEngineMicrosoftDefenderRuleIfNeeded = async () => {
// FIXME:PT implemnet
import type { KbnClient } from '@kbn/test';
import type { ToolingLog } from '@kbn/tooling-log';
import { dump } from '../../common/utils';
import { createRule, findRules } from '../../common/detection_rules_services';
import type { RuleResponse } from '../../../../common/api/detection_engine';

export const createDetectionEngineMicrosoftDefenderRuleIfNeeded = async (
kbnClient: KbnClient,
log: ToolingLog,
/** Index namesapce. If defined, then the Index patterns used the SIEM rule will include this value */
namespace?: string
): Promise<RuleResponse> => {
const ruleName = 'Promote Microsoft Defender alerts';
const tag = 'dev-script-run-microsoft-defend-host';
const indexNamespace = namespace ? `-${namespace}` : '';
const index = [`logs-microsoft_defender_endpoint.log${indexNamespace}*`];
const ruleQueryValue = 'cloud.instance.id:*';

const { data } = await findRules(kbnClient, {
filter: `alert.attributes.tags:("${tag}")`,
});

if (data.length) {
log.info(
`Detection engine rule for Microsoft Defender alerts already exists [${data[0].name}]. No need to create a new one.`
);

return data[0];
}

log.info(`Creating new detection engine rule named [${ruleName}] for Microsoft Defender`);

const createdRule = await createRule(kbnClient, {
index,
query: ruleQueryValue,
from: 'now-3660s',
name: ruleName,
description: `Created by dev script located at: ${__filename}`,
tags: [tag],
});

log.verbose(dump(createdRule));

return createdRule;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,58 @@
* 2.0.
*/

export const createMicrosoftDefenderForEndpointConnectorIfNeeded = async () => {
// FIXME:PT implement
import type { ToolingLog } from '@kbn/tooling-log';
import type { KbnClient } from '@kbn/test';
import { MICROSOFT_DEFENDER_ENDPOINT_CONNECTOR_ID } from '@kbn/stack-connectors-plugin/common/microsoft_defender_endpoint/constants';
import { dump } from '../../common/utils';
import { fetchActiveSpace } from '../../common/spaces';
import { createConnector, fetchConnectorByType } from '../../common/connectors_services';

interface CreateMicrosoftDefenderForEndpointConnectorIfNeededOptions {
kbnClient: KbnClient;
log: ToolingLog;
clientId: string;
tenantId: string;
oAuthServerUrl: string;
oAuthScope: string;
apiUrl: string;
clientSecret: string;
name?: string;
}

export const createMicrosoftDefenderForEndpointConnectorIfNeeded = async ({
kbnClient,
log,
clientId,
tenantId,
oAuthServerUrl,
oAuthScope,
apiUrl,
clientSecret,
name: _name,
}: CreateMicrosoftDefenderForEndpointConnectorIfNeededOptions): Promise<void> => {
const existingConnector = await fetchConnectorByType(
kbnClient,
MICROSOFT_DEFENDER_ENDPOINT_CONNECTOR_ID
);

if (existingConnector) {
log.debug(`Nothing to do. A connector for SentinelOne is already configured`);
log.verbose(dump(existingConnector));
return;
}

const name =
_name ?? `Microsoft Defender Dev instance (space: ${(await fetchActiveSpace(kbnClient)).id})`;

log.info(`Creating Microsoft Defender Connector with name: ${name}`);

const newConnector = await createConnector(kbnClient, {
name,
connector_type_id: MICROSOFT_DEFENDER_ENDPOINT_CONNECTOR_ID,
config: { clientId, tenantId, oAuthServerUrl, oAuthScope, apiUrl },
secrets: { clientSecret },
});

log.verbose(dump(newConnector));
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import type { ToolingLog } from '@kbn/tooling-log';
import type { KbnClient } from '@kbn/test';
import type { IndexResponse } from '@elastic/elasticsearch/lib/api/types';
import { MicrosoftDefenderDataGenerator } from '../../../../common/endpoint/data_generators/microsoft_defender_data_generator';
import { MICROSOFT_DEFENDER_INTEGRATION_PACKAGE_NAME } from './constants';
import { installIntegration } from '../../common/fleet_services';
Expand All @@ -15,12 +16,16 @@ import { createToolingLogger } from '../../../../common/endpoint/data_loaders/ut
export interface OnboardVmHostWithMicrosoftDefenderOptions {
kbnClient: KbnClient;
log?: ToolingLog;
vmName?: string;
forceNewHost?: boolean;
}

export const onboardVmHostWithMicrosoftDefender = async ({
kbnClient,
log = createToolingLogger(),
}: OnboardVmHostWithMicrosoftDefenderOptions) => {
// FIXME:PT implement creation of new VM and connect it to MS Defender managment system

log?.warning(`
Creation of a VM host running Microsoft Defender for Endpoint is not yet implemented. However, an event
will be indexed that will enable testing within Kibana only.
Expand All @@ -31,10 +36,10 @@ export const onboardVmHostWithMicrosoftDefender = async ({
const indexName = 'logs-microsoft_defender_endpoint.log-default';
const docToCreate = new MicrosoftDefenderDataGenerator().generateEndpointLog();

log.verbose(`Creating event in [l${indexName}]:\n ${JSON.stringify(docToCreate, null, 2)}`);
log.verbose(`Creating event in [${indexName}]:\n ${JSON.stringify(docToCreate, null, 2)}`);

const indexedDoc = await kbnClient
.request({
.request<IndexResponse>({
method: 'POST',
path: 'api/console/proxy',
headers: { 'elastic-api-version': '2023-10-31' },
Expand Down

0 comments on commit 22c09e0

Please sign in to comment.