From 36a890759f630bbdedf46e2174cb30538e84d8b9 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Tue, 22 Oct 2024 15:19:59 -0700 Subject: [PATCH 01/15] Adding EDR feature privilege --- .../server/action_type_registry.mock.ts | 2 +- .../server/action_type_registry.test.ts | 10 +++--- .../actions/server/action_type_registry.ts | 17 ++------- .../connector/methods/execute/execute.ts | 4 +-- .../actions_authorization.test.ts | 4 +-- .../authorization/actions_authorization.ts | 11 +----- x-pack/plugins/actions/server/feature.ts | 36 ++++++++++++++++--- .../server/lib/action_executor.test.ts | 6 ++-- .../actions/server/lib/action_executor.ts | 25 ++++--------- ...ges.ts => get_action_kibana_privileges.ts} | 9 ++--- .../server/connector_types/email/index.ts | 2 ++ 11 files changed, 58 insertions(+), 68 deletions(-) rename x-pack/plugins/actions/server/lib/{get_system_action_kibana_privileges.ts => get_action_kibana_privileges.ts} (71%) diff --git a/x-pack/plugins/actions/server/action_type_registry.mock.ts b/x-pack/plugins/actions/server/action_type_registry.mock.ts index 399bf6ed22684..2545b7c1fab6c 100644 --- a/x-pack/plugins/actions/server/action_type_registry.mock.ts +++ b/x-pack/plugins/actions/server/action_type_registry.mock.ts @@ -19,7 +19,7 @@ const createActionTypeRegistryMock = () => { isActionExecutable: jest.fn(), isSystemActionType: jest.fn(), getUtils: jest.fn(), - getSystemActionKibanaPrivileges: jest.fn(), + getActionKibanaPrivileges: jest.fn(), }; return mocked; }; diff --git a/x-pack/plugins/actions/server/action_type_registry.test.ts b/x-pack/plugins/actions/server/action_type_registry.test.ts index 88ae6c3678552..a00dc331e933e 100644 --- a/x-pack/plugins/actions/server/action_type_registry.test.ts +++ b/x-pack/plugins/actions/server/action_type_registry.test.ts @@ -767,7 +767,7 @@ describe('actionTypeRegistry', () => { }); }); - describe('getSystemActionKibanaPrivileges()', () => { + describe('getActionKibanaPrivileges()', () => { it('should get the kibana privileges correctly for system actions', () => { const registry = new ActionTypeRegistry(actionTypeRegistryParams); @@ -786,7 +786,7 @@ describe('actionTypeRegistry', () => { executor, }); - const result = registry.getSystemActionKibanaPrivileges('test.system-action'); + const result = registry.getActionKibanaPrivileges('test.system-action'); expect(result).toEqual(['test/create']); }); @@ -807,7 +807,7 @@ describe('actionTypeRegistry', () => { executor, }); - const result = registry.getSystemActionKibanaPrivileges('test.system-action'); + const result = registry.getActionKibanaPrivileges('test.system-action'); expect(result).toEqual([]); }); @@ -827,7 +827,7 @@ describe('actionTypeRegistry', () => { executor, }); - const result = registry.getSystemActionKibanaPrivileges('foo'); + const result = registry.getActionKibanaPrivileges('foo'); expect(result).toEqual([]); }); @@ -850,7 +850,7 @@ describe('actionTypeRegistry', () => { executor, }); - registry.getSystemActionKibanaPrivileges('test.system-action', { foo: 'bar' }); + registry.getActionKibanaPrivileges('test.system-action', { foo: 'bar' }); expect(getKibanaPrivileges).toHaveBeenCalledWith({ params: { foo: 'bar' } }); }); }); diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index a5626450d9346..505b64cfc5ecb 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -113,18 +113,14 @@ export class ActionTypeRegistry { Boolean(this.actionTypes.get(actionTypeId)?.isSystemActionType); /** - * Returns the kibana privileges of a system action type + * Returns the kibana privileges */ - public getSystemActionKibanaPrivileges( + public getActionKibanaPrivileges( actionTypeId: string, params?: Params ): string[] { const actionType = this.actionTypes.get(actionTypeId); - if (!actionType?.isSystemActionType) { - return []; - } - return actionType?.getKibanaPrivileges?.({ params }) ?? []; } @@ -175,15 +171,6 @@ export class ActionTypeRegistry { ); } - if (!actionType.isSystemActionType && actionType.getKibanaPrivileges) { - throw new Error( - i18n.translate('xpack.actions.actionTypeRegistry.register.invalidKibanaPrivileges', { - defaultMessage: - 'Kibana privilege authorization is only supported for system action types', - }) - ); - } - const maxAttempts = this.actionsConfigUtils.getMaxAttempts({ actionTypeId: actionType.id, actionTypeMaxAttempts: actionType.maxAttempts, diff --git a/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts b/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts index f9922e0b61a8d..f5034703f8cdf 100644 --- a/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts +++ b/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts @@ -7,7 +7,7 @@ import { v4 as uuidv4 } from 'uuid'; import { RawAction, ActionTypeExecutorResult } from '../../../../types'; -import { getSystemActionKibanaPrivileges } from '../../../../lib/get_system_action_kibana_privileges'; +import { getActionKibanaPrivileges } from '../../../../lib/get_action_kibana_privileges'; import { isPreconfigured } from '../../../../lib/is_preconfigured'; import { isSystemAction } from '../../../../lib/is_system_action'; import { @@ -30,7 +30,7 @@ export async function execute( (await getAuthorizationModeBySource(context.unsecuredSavedObjectsClient, source)) === AuthorizationMode.RBAC ) { - const additionalPrivileges = getSystemActionKibanaPrivileges(context, actionId, params); + const additionalPrivileges = getActionKibanaPrivileges(context, actionId, params); let actionTypeId: string | undefined; try { diff --git a/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts b/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts index 41eab4fbc2e43..0bb88b4415c0b 100644 --- a/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts +++ b/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts @@ -14,7 +14,7 @@ import { } from '../constants/saved_objects'; import { AuthorizationMode } from './get_authorization_mode_by_source'; import { - CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG, + CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG, CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG, } from '../feature'; import { forEach } from 'lodash'; @@ -23,7 +23,7 @@ const request = {} as KibanaRequest; const mockAuthorizationAction = (type: string, operation: string) => `${type}/${operation}`; const BASIC_EXECUTE_AUTHZ = `api:${CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG}`; -const ADVANCED_EXECUTE_AUTHZ = `api:${CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG}`; +const ADVANCED_EXECUTE_AUTHZ = `api:${CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG}`; function mockSecurity() { const security = securityMock.createSetup(); diff --git a/x-pack/plugins/actions/server/authorization/actions_authorization.ts b/x-pack/plugins/actions/server/authorization/actions_authorization.ts index 5739af64050ee..a17b23c828afc 100644 --- a/x-pack/plugins/actions/server/authorization/actions_authorization.ts +++ b/x-pack/plugins/actions/server/authorization/actions_authorization.ts @@ -12,7 +12,6 @@ import { ACTION_SAVED_OBJECT_TYPE, ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, } from '../constants/saved_objects'; -import { isBidirectionalConnectorType } from '../lib/bidirectional_connectors'; import { AuthorizationMode } from './get_authorization_mode_by_source'; export interface ConstructorOptions { @@ -74,15 +73,7 @@ export class ActionsAuthorization { : [authorization.actions.savedObject.get(ACTION_SAVED_OBJECT_TYPE, operation)]; const { hasAllRequested } = await checkPrivileges({ - kibana: [ - ...privileges, - ...additionalPrivileges, - // SentinelOne and Crowdstrike sub-actions require that a user have `all` privilege to Actions and Connectors. - // This is a temporary solution until a more robust RBAC approach can be implemented for sub-actions - isBidirectionalConnectorType(actionTypeId) - ? 'api:actions:execute-advanced-connectors' - : 'api:actions:execute-basic-connectors', - ], + kibana: [...privileges, ...additionalPrivileges], }); if (!hasAllRequested) { throw Boom.forbidden( diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index d4a9d3a3537bf..5522db43ef133 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -14,7 +14,9 @@ import { CONNECTOR_TOKEN_SAVED_OBJECT_TYPE, } from './constants/saved_objects'; -export const CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-advanced-connectors'; +export const CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-edr-connectors'; +export const CONNECTORS_EDR_EXECUTE_PRIVILEGE = `api:${CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG}`; + export const CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-basic-connectors'; /** @@ -38,10 +40,7 @@ export const ACTIONS_FEATURE = { privileges: { all: { app: [], - api: [ - CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG, - CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG, - ], + api: [CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG, CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG], catalogue: [], management: { insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], @@ -71,4 +70,31 @@ export const ACTIONS_FEATURE = { ui: ['show', 'execute'], }, }, + subFeatures: [ + { + name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureName', { + defaultMessage: 'EDR Connectors', + }), + privilegeGroups: [ + { + groupType: 'independent', + privileges: [ + { + api: [CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG], + id: 'execute-edr-connectors', + name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureDetails', { + defaultMessage: 'Execute advanced EDR connectors', + }), + includeIn: 'all', + savedObject: { + all: [ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, CONNECTOR_TOKEN_SAVED_OBJECT_TYPE], + read: [ACTION_SAVED_OBJECT_TYPE], + }, + ui: ['execute-edr-connectors'], + }, + ], + }, + ], + }, + ], }; diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index 6e4ec1b69c876..9bcc551ae20ab 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -1370,7 +1370,7 @@ describe('System actions', () => { getKibanaPrivileges: () => ['test/create'], }); connectorTypeRegistry.isSystemActionType.mockReturnValueOnce(true); - connectorTypeRegistry.getSystemActionKibanaPrivileges.mockReturnValueOnce(['test/create']); + connectorTypeRegistry.getActionKibanaPrivileges.mockReturnValueOnce(['test/create']); await actionExecutor.execute({ ...executeParams, actionId: 'system-connector-.cases' }); @@ -1387,7 +1387,7 @@ describe('System actions', () => { getKibanaPrivileges: () => ['test/create'], }); connectorTypeRegistry.isSystemActionType.mockReturnValueOnce(true); - connectorTypeRegistry.getSystemActionKibanaPrivileges.mockReturnValueOnce(['test/create']); + connectorTypeRegistry.getActionKibanaPrivileges.mockReturnValueOnce(['test/create']); await actionExecutor.execute({ ...executeParams, @@ -1395,7 +1395,7 @@ describe('System actions', () => { actionId: 'system-connector-.cases', }); - expect(connectorTypeRegistry.getSystemActionKibanaPrivileges).toHaveBeenCalledWith('.cases', { + expect(connectorTypeRegistry.getActionKibanaPrivileges).toHaveBeenCalledWith('.cases', { foo: 'bar', }); diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index a636f4b41566c..3e58038be1c2e 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -53,7 +53,6 @@ import { RelatedSavedObjects } from './related_saved_objects'; import { createActionEventLogRecordObject } from './create_action_event_log_record_object'; import { ActionExecutionError, ActionExecutionErrorReason } from './errors/action_execution_error'; import type { ActionsAuthorization } from '../authorization/actions_authorization'; -import { isBidirectionalConnectorType } from './bidirectional_connectors'; // 1,000,000 nanoseconds in 1 millisecond const Millis2Nanos = 1000 * 1000; @@ -722,25 +721,13 @@ const ensureAuthorizedToExecute = async ({ authorization, }: EnsureAuthorizedToExecuteOpts) => { try { - if (actionTypeRegistry.isSystemActionType(actionTypeId)) { - const additionalPrivileges = actionTypeRegistry.getSystemActionKibanaPrivileges( - actionTypeId, - params - ); + const additionalPrivileges = actionTypeRegistry.getActionKibanaPrivileges(actionTypeId, params); - await authorization.ensureAuthorized({ - operation: 'execute', - additionalPrivileges, - actionTypeId, - }); - } else if (isBidirectionalConnectorType(actionTypeId)) { - // SentinelOne and Crowdstrike sub-actions require that a user have `all` privilege to Actions and Connectors. - // This is a temporary solution until a more robust RBAC approach can be implemented for sub-actions - await authorization.ensureAuthorized({ - operation: 'execute', - actionTypeId, - }); - } + await authorization.ensureAuthorized({ + operation: 'execute', + additionalPrivileges, + actionTypeId, + }); } catch (error) { throw new ActionExecutionError(error.message, ActionExecutionErrorReason.Authorization, { actionId, diff --git a/x-pack/plugins/actions/server/lib/get_system_action_kibana_privileges.ts b/x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts similarity index 71% rename from x-pack/plugins/actions/server/lib/get_system_action_kibana_privileges.ts rename to x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts index ef3b8ff853d17..ec5336d24a925 100644 --- a/x-pack/plugins/actions/server/lib/get_system_action_kibana_privileges.ts +++ b/x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts @@ -8,7 +8,7 @@ import { ActionsClientContext } from '../actions_client'; import { ExecuteOptions } from './action_executor'; -export function getSystemActionKibanaPrivileges( +export function getActionKibanaPrivileges( context: ActionsClientContext, connectorId: string, params?: ExecuteOptions['params'] @@ -17,11 +17,8 @@ export function getSystemActionKibanaPrivileges( (connector) => connector.id === connectorId ); - const additionalPrivileges = inMemoryConnector?.isSystemAction - ? context.actionTypeRegistry.getSystemActionKibanaPrivileges( - inMemoryConnector.actionTypeId, - params - ) + const additionalPrivileges = inMemoryConnector + ? context.actionTypeRegistry.getActionKibanaPrivileges(inMemoryConnector.actionTypeId, params) : []; return additionalPrivileges; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts index 3a1d01732eb7d..cb916d70b9d38 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts @@ -22,6 +22,7 @@ import { UptimeConnectorFeatureId, SecurityConnectorFeatureId, } from '@kbn/actions-plugin/common/connector_feature_config'; +import { CONNECTORS_EDR_EXECUTE_PRIVILEGE } from '@kbn/actions-plugin/server/feature'; import { withoutMustacheTemplate } from '@kbn/actions-plugin/common'; import { renderMustacheObject, @@ -248,6 +249,7 @@ export function getConnectorType(params: GetConnectorTypeParams): EmailConnector }, renderParameterTemplates, executor: curry(executor)({ publicBaseUrl }), + getKibanaPrivileges: () => [CONNECTORS_EDR_EXECUTE_PRIVILEGE], }; } From fdf72129cce3c2631bbdd167d1c19d6301723e3c Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 23 Oct 2024 11:15:41 -0700 Subject: [PATCH 02/15] Updating the ui --- packages/kbn-actions-types/action_types.ts | 1 + .../transform_connector_types_response.ts | 2 ++ .../kbn-alerts-ui-shared/src/common/types/action_types.ts | 1 + .../actions/common/routes/connector/response/schemas/v1.ts | 3 +++ .../actions/common/routes/connector/response/types/v1.ts | 1 + x-pack/plugins/actions/common/types.ts | 1 + x-pack/plugins/actions/server/action_type_registry.ts | 1 + .../application/connector/schemas/connector_type_schema.ts | 1 + .../server/application/connector/types/connector_type.ts | 1 + x-pack/plugins/actions/server/feature.ts | 4 ++-- .../transforms/transform_list_types_response/v1.ts | 2 ++ x-pack/plugins/actions/server/types.ts | 1 + .../uptime/public/legacy_uptime/state/api/alerts.ts | 2 ++ .../stack_connectors/server/connector_types/email/index.ts | 1 + .../public/application/lib/capabilities.ts | 5 +++-- .../action_connector_form/edit_connector_flyout/header.tsx | 6 +++--- .../action_connector_form/edit_connector_flyout/index.tsx | 2 +- .../components/actions_connectors_list.tsx | 5 ++++- 18 files changed, 31 insertions(+), 9 deletions(-) diff --git a/packages/kbn-actions-types/action_types.ts b/packages/kbn-actions-types/action_types.ts index 4f04c02a5fa34..b49bf2d631f12 100644 --- a/packages/kbn-actions-types/action_types.ts +++ b/packages/kbn-actions-types/action_types.ts @@ -18,4 +18,5 @@ export interface ActionType { minimumLicenseRequired: LicenseType; supportedFeatureIds: string[]; isSystemActionType: boolean; + isEdrConnectorType: boolean; } diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts index 576df0c171964..78dc550aff948 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts @@ -15,6 +15,7 @@ const transformConnectorType: RewriteRequestCase = ({ minimum_license_required: minimumLicenseRequired, supported_feature_ids: supportedFeatureIds, is_system_action_type: isSystemActionType, + is_edr_connector_type: isEdrConnectorType, ...res }: AsApiContract) => ({ enabledInConfig, @@ -22,6 +23,7 @@ const transformConnectorType: RewriteRequestCase = ({ minimumLicenseRequired, supportedFeatureIds, isSystemActionType, + isEdrConnectorType, ...res, }); diff --git a/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts b/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts index 753db07057e55..eabede0165754 100644 --- a/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts +++ b/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts @@ -130,6 +130,7 @@ export interface ActionTypeModel = PublicMethodsOf< diff --git a/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts index 096e2f2943d80..1528eff9ceabc 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts @@ -97,6 +97,9 @@ export const connectorTypesResponseSchema = schema.object({ is_system_action_type: schema.boolean({ meta: { description: 'Indicates whether the action is a system action.' }, }), + is_edr_connector_type: schema.boolean({ + meta: { description: 'Indicates whether the connector is an EDR connector.' }, + }), }); export const connectorExecuteResponseSchema = schema.object({ diff --git a/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts index 499cc2ec21d48..0095fe094b86d 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts @@ -41,6 +41,7 @@ export interface ConnectorTypesResponse { minimum_license_required: ConnectorTypesResponseSchemaType['minimum_license_required']; supported_feature_ids: ConnectorTypesResponseSchemaType['supported_feature_ids']; is_system_action_type: ConnectorTypesResponseSchemaType['is_system_action_type']; + is_edr_connector_type: ConnectorTypesResponseSchemaType['is_edr_connector_type']; } type ConnectorExecuteResponseSchemaType = TypeOf; diff --git a/x-pack/plugins/actions/common/types.ts b/x-pack/plugins/actions/common/types.ts index 7540056057873..2dbddb072a548 100644 --- a/x-pack/plugins/actions/common/types.ts +++ b/x-pack/plugins/actions/common/types.ts @@ -24,6 +24,7 @@ export interface ActionType { minimumLicenseRequired: LicenseType; supportedFeatureIds: string[]; isSystemActionType: boolean; + isEdrConnectorType: boolean; } export enum InvalidEmailReason { diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index 505b64cfc5ecb..2c5b31b3498cf 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -238,6 +238,7 @@ export class ActionTypeRegistry { enabledInLicense: !!this.licenseState.isLicenseValidForActionType(actionType).isValid, supportedFeatureIds: actionType.supportedFeatureIds, isSystemActionType: !!actionType.isSystemActionType, + isEdrConnectorType: !!actionType.isEdrConnectorType, })) ); } diff --git a/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts b/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts index e5556ab5c4a33..dccc40db072b1 100644 --- a/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts +++ b/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts @@ -23,4 +23,5 @@ export const connectorTypeSchema = schema.object({ ]), supportedFeatureIds: schema.arrayOf(schema.string()), isSystemActionType: schema.boolean(), + isEdrConnectorType: schema.boolean(), }); diff --git a/x-pack/plugins/actions/server/application/connector/types/connector_type.ts b/x-pack/plugins/actions/server/application/connector/types/connector_type.ts index 64be01365a8ba..100c919e17c8a 100644 --- a/x-pack/plugins/actions/server/application/connector/types/connector_type.ts +++ b/x-pack/plugins/actions/server/application/connector/types/connector_type.ts @@ -19,4 +19,5 @@ export interface ConnectorType { minimumLicenseRequired: ConnectorTypeSchemaType['minimumLicenseRequired']; supportedFeatureIds: ConnectorTypeSchemaType['supportedFeatureIds']; isSystemActionType: ConnectorTypeSchemaType['isSystemActionType']; + isEdrConnectorType: ConnectorTypeSchemaType['isEdrConnectorType']; } diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index 5522db43ef133..2998b3ef33b86 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -81,7 +81,7 @@ export const ACTIONS_FEATURE = { privileges: [ { api: [CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG], - id: 'execute-edr-connectors', + id: 'executeEdrConnectors', name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureDetails', { defaultMessage: 'Execute advanced EDR connectors', }), @@ -90,7 +90,7 @@ export const ACTIONS_FEATURE = { all: [ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, CONNECTOR_TOKEN_SAVED_OBJECT_TYPE], read: [ACTION_SAVED_OBJECT_TYPE], }, - ui: ['execute-edr-connectors'], + ui: ['executeEdrConnectors'], }, ], }, diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts index e32bec2f9e1a1..5df48f8a3f435 100644 --- a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts +++ b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts @@ -21,6 +21,7 @@ export const transformListTypesResponse = ( minimumLicenseRequired, supportedFeatureIds, isSystemActionType, + isEdrConnectorType, }) => ({ id, name, @@ -30,6 +31,7 @@ export const transformListTypesResponse = ( minimum_license_required: minimumLicenseRequired, supported_feature_ids: supportedFeatureIds, is_system_action_type: isSystemActionType, + is_edr_connector_type: isEdrConnectorType, }) ); }; diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index d7c3497edc376..631ecd4867a10 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -199,6 +199,7 @@ export interface ActionType< connector?: (config: Config, secrets: Secrets) => string | null; }; isSystemActionType?: boolean; + isEdrConnectorType?: boolean; /** * Additional Kibana privileges to be checked by the actions framework. * Use it if you want to perform extra authorization checks based on a Kibana feature. diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts index 0157a0fb34673..3bd69e5db97f6 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts @@ -172,6 +172,7 @@ export const fetchActionTypes = async (): Promise => { minimum_license_required: minimumLicenseRequired, supported_feature_ids: supportedFeatureIds, is_system_action_type: isSystemActionType, + is_edr_connector_type: isEdrConnectorType, ...res }: AsApiContract) => ({ ...res, @@ -180,6 +181,7 @@ export const fetchActionTypes = async (): Promise => { minimumLicenseRequired, supportedFeatureIds, isSystemActionType, + isEdrConnectorType, }) ); }; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts index cb916d70b9d38..b1f01688ab61d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts @@ -249,6 +249,7 @@ export function getConnectorType(params: GetConnectorTypeParams): EmailConnector }, renderParameterTemplates, executor: curry(executor)({ publicBaseUrl }), + isEdrConnectorType: true, getKibanaPrivileges: () => [CONNECTORS_EDR_EXECUTE_PRIVILEGE], }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts index 6d12ffafe0ef8..52ec8fd11d1f5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts @@ -18,8 +18,9 @@ type Capabilities = Record; export const hasShowActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.show; export const hasSaveActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.save; -export const hasExecuteActionsCapability = (capabilities: Capabilities, actionTypeId?: string) => - actionTypeId === '.sentinelone' ? capabilities?.actions?.save : capabilities?.actions?.execute; +export const hasExecuteActionsCapability = (capabilities: Capabilities, isEdrConnector?: boolean) => + isEdrConnector ? capabilities?.actions?.executeEdrConnectors : capabilities?.actions?.execute; + export const hasDeleteActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.delete; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx index 691e7d1ff87b5..d82a114531909 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx @@ -29,9 +29,9 @@ import { hasExecuteActionsCapability } from '../../../lib/capabilities'; const FlyoutHeaderComponent: React.FC<{ isExperimental?: boolean; + isEdrConnectorType?: boolean; isPreconfigured: boolean; connectorName: string; - connectorTypeId: string; connectorTypeDesc: string; selectedTab: EditConnectorTabs; setTab: (nextPage: EditConnectorTabs) => void; @@ -39,9 +39,9 @@ const FlyoutHeaderComponent: React.FC<{ }> = ({ icon, isExperimental = false, + isEdrConnectorType = false, isPreconfigured, connectorName, - connectorTypeId, connectorTypeDesc, selectedTab, setTab, @@ -51,7 +51,7 @@ const FlyoutHeaderComponent: React.FC<{ } = useKibana().services; const { euiTheme } = useEuiTheme(); - const canExecute = hasExecuteActionsCapability(capabilities, connectorTypeId); + const canExecute = hasExecuteActionsCapability(capabilities, isEdrConnectorType); const setConfigurationTab = useCallback(() => { setTab(EditConnectorTabs.Configuration); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index e787f3eac42bf..a06876904493a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -316,12 +316,12 @@ const EditConnectorFlyoutComponent: React.FC = ({ {selectedTab === EditConnectorTabs.Configuration && renderConfigurationTab()} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index e00b08d9c8512..c39a0acc80821 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -339,7 +339,10 @@ const ActionsConnectorsList = ({ Date: Wed, 23 Oct 2024 11:38:55 -0700 Subject: [PATCH 03/15] Rename to action instead of connector --- packages/kbn-actions-types/action_types.ts | 2 +- .../transform_connector_types_response.ts | 4 ++-- .../src/common/types/action_types.ts | 2 +- .../routes/connector/response/schemas/v1.ts | 4 ++-- .../routes/connector/response/types/v1.ts | 2 +- x-pack/plugins/actions/common/types.ts | 2 +- .../actions/server/action_type_registry.ts | 18 +++++++++++++++++- .../connector/schemas/connector_type_schema.ts | 2 +- .../connector/types/connector_type.ts | 2 +- x-pack/plugins/actions/server/feature.ts | 2 +- .../transform_list_types_response/v1.ts | 4 ++-- x-pack/plugins/actions/server/types.ts | 2 +- .../public/legacy_uptime/state/api/alerts.ts | 4 ++-- .../server/connector_types/email/index.ts | 2 +- .../public/application/lib/capabilities.ts | 4 ++-- .../edit_connector_flyout/header.tsx | 6 +++--- .../edit_connector_flyout/index.tsx | 2 +- .../components/actions_connectors_list.tsx | 2 +- 18 files changed, 41 insertions(+), 25 deletions(-) diff --git a/packages/kbn-actions-types/action_types.ts b/packages/kbn-actions-types/action_types.ts index b49bf2d631f12..8b898765a647a 100644 --- a/packages/kbn-actions-types/action_types.ts +++ b/packages/kbn-actions-types/action_types.ts @@ -18,5 +18,5 @@ export interface ActionType { minimumLicenseRequired: LicenseType; supportedFeatureIds: string[]; isSystemActionType: boolean; - isEdrConnectorType: boolean; + isEdrActionType: boolean; } diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts index 78dc550aff948..c82c8abbf26dc 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_connector_types/transform_connector_types_response.ts @@ -15,7 +15,7 @@ const transformConnectorType: RewriteRequestCase = ({ minimum_license_required: minimumLicenseRequired, supported_feature_ids: supportedFeatureIds, is_system_action_type: isSystemActionType, - is_edr_connector_type: isEdrConnectorType, + is_edr_action_type: isEdrActionType, ...res }: AsApiContract) => ({ enabledInConfig, @@ -23,7 +23,7 @@ const transformConnectorType: RewriteRequestCase = ({ minimumLicenseRequired, supportedFeatureIds, isSystemActionType, - isEdrConnectorType, + isEdrActionType, ...res, }); diff --git a/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts b/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts index eabede0165754..fc0023e6729d4 100644 --- a/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts +++ b/packages/kbn-alerts-ui-shared/src/common/types/action_types.ts @@ -130,7 +130,7 @@ export interface ActionTypeModel = PublicMethodsOf< diff --git a/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts index 1528eff9ceabc..cf511f09962bb 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts @@ -97,8 +97,8 @@ export const connectorTypesResponseSchema = schema.object({ is_system_action_type: schema.boolean({ meta: { description: 'Indicates whether the action is a system action.' }, }), - is_edr_connector_type: schema.boolean({ - meta: { description: 'Indicates whether the connector is an EDR connector.' }, + is_edr_action_type: schema.boolean({ + meta: { description: 'Indicates whether the action is an EDR action.' }, }), }); diff --git a/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts index 0095fe094b86d..43affbfca7184 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts @@ -41,7 +41,7 @@ export interface ConnectorTypesResponse { minimum_license_required: ConnectorTypesResponseSchemaType['minimum_license_required']; supported_feature_ids: ConnectorTypesResponseSchemaType['supported_feature_ids']; is_system_action_type: ConnectorTypesResponseSchemaType['is_system_action_type']; - is_edr_connector_type: ConnectorTypesResponseSchemaType['is_edr_connector_type']; + is_edr_action_type: ConnectorTypesResponseSchemaType['is_edr_action_type']; } type ConnectorExecuteResponseSchemaType = TypeOf; diff --git a/x-pack/plugins/actions/common/types.ts b/x-pack/plugins/actions/common/types.ts index 2dbddb072a548..d520b50d12493 100644 --- a/x-pack/plugins/actions/common/types.ts +++ b/x-pack/plugins/actions/common/types.ts @@ -24,7 +24,7 @@ export interface ActionType { minimumLicenseRequired: LicenseType; supportedFeatureIds: string[]; isSystemActionType: boolean; - isEdrConnectorType: boolean; + isEdrActionType: boolean; } export enum InvalidEmailReason { diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index 2c5b31b3498cf..2f9f3e7872cdc 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -121,6 +121,10 @@ export class ActionTypeRegistry { ): string[] { const actionType = this.actionTypes.get(actionTypeId); + if (!actionType?.isSystemActionType || !actionType?.isEdrActionType) { + return []; + } + return actionType?.getKibanaPrivileges?.({ params }) ?? []; } @@ -171,6 +175,18 @@ export class ActionTypeRegistry { ); } + if ( + (!actionType.isSystemActionType || !actionType.isEdrActionType) && + actionType.getKibanaPrivileges + ) { + throw new Error( + i18n.translate('xpack.actions.actionTypeRegistry.register.invalidKibanaPrivileges', { + defaultMessage: + 'Kibana privilege authorization is only supported for system and EDR action types', + }) + ); + } + const maxAttempts = this.actionsConfigUtils.getMaxAttempts({ actionTypeId: actionType.id, actionTypeMaxAttempts: actionType.maxAttempts, @@ -238,7 +254,7 @@ export class ActionTypeRegistry { enabledInLicense: !!this.licenseState.isLicenseValidForActionType(actionType).isValid, supportedFeatureIds: actionType.supportedFeatureIds, isSystemActionType: !!actionType.isSystemActionType, - isEdrConnectorType: !!actionType.isEdrConnectorType, + isEdrActionType: !!actionType.isEdrActionType, })) ); } diff --git a/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts b/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts index dccc40db072b1..13427efff2569 100644 --- a/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts +++ b/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts @@ -23,5 +23,5 @@ export const connectorTypeSchema = schema.object({ ]), supportedFeatureIds: schema.arrayOf(schema.string()), isSystemActionType: schema.boolean(), - isEdrConnectorType: schema.boolean(), + isEdrActionType: schema.boolean(), }); diff --git a/x-pack/plugins/actions/server/application/connector/types/connector_type.ts b/x-pack/plugins/actions/server/application/connector/types/connector_type.ts index 100c919e17c8a..9cf78a85bdc17 100644 --- a/x-pack/plugins/actions/server/application/connector/types/connector_type.ts +++ b/x-pack/plugins/actions/server/application/connector/types/connector_type.ts @@ -19,5 +19,5 @@ export interface ConnectorType { minimumLicenseRequired: ConnectorTypeSchemaType['minimumLicenseRequired']; supportedFeatureIds: ConnectorTypeSchemaType['supportedFeatureIds']; isSystemActionType: ConnectorTypeSchemaType['isSystemActionType']; - isEdrConnectorType: ConnectorTypeSchemaType['isEdrConnectorType']; + isEdrActionType: ConnectorTypeSchemaType['isEdrActionType']; } diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index 2998b3ef33b86..40a408863a5c5 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -90,7 +90,7 @@ export const ACTIONS_FEATURE = { all: [ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, CONNECTOR_TOKEN_SAVED_OBJECT_TYPE], read: [ACTION_SAVED_OBJECT_TYPE], }, - ui: ['executeEdrConnectors'], + ui: ['executeEdr'], }, ], }, diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts index 5df48f8a3f435..bc2909c0aec9c 100644 --- a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts +++ b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts @@ -21,7 +21,7 @@ export const transformListTypesResponse = ( minimumLicenseRequired, supportedFeatureIds, isSystemActionType, - isEdrConnectorType, + isEdrActionType, }) => ({ id, name, @@ -31,7 +31,7 @@ export const transformListTypesResponse = ( minimum_license_required: minimumLicenseRequired, supported_feature_ids: supportedFeatureIds, is_system_action_type: isSystemActionType, - is_edr_connector_type: isEdrConnectorType, + is_edr_action_type: isEdrActionType, }) ); }; diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 631ecd4867a10..5bda49413ecd9 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -199,7 +199,7 @@ export interface ActionType< connector?: (config: Config, secrets: Secrets) => string | null; }; isSystemActionType?: boolean; - isEdrConnectorType?: boolean; + isEdrActionType?: boolean; /** * Additional Kibana privileges to be checked by the actions framework. * Use it if you want to perform extra authorization checks based on a Kibana feature. diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts index 3bd69e5db97f6..63caca2347c7f 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/state/api/alerts.ts @@ -172,7 +172,7 @@ export const fetchActionTypes = async (): Promise => { minimum_license_required: minimumLicenseRequired, supported_feature_ids: supportedFeatureIds, is_system_action_type: isSystemActionType, - is_edr_connector_type: isEdrConnectorType, + is_edr_action_type: isEdrActionType, ...res }: AsApiContract) => ({ ...res, @@ -181,7 +181,7 @@ export const fetchActionTypes = async (): Promise => { minimumLicenseRequired, supportedFeatureIds, isSystemActionType, - isEdrConnectorType, + isEdrActionType, }) ); }; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts index b1f01688ab61d..d4401f182c4fc 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts @@ -249,7 +249,7 @@ export function getConnectorType(params: GetConnectorTypeParams): EmailConnector }, renderParameterTemplates, executor: curry(executor)({ publicBaseUrl }), - isEdrConnectorType: true, + isEdrActionType: true, getKibanaPrivileges: () => [CONNECTORS_EDR_EXECUTE_PRIVILEGE], }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts index 52ec8fd11d1f5..1ea5774845dd1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts @@ -18,8 +18,8 @@ type Capabilities = Record; export const hasShowActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.show; export const hasSaveActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.save; -export const hasExecuteActionsCapability = (capabilities: Capabilities, isEdrConnector?: boolean) => - isEdrConnector ? capabilities?.actions?.executeEdrConnectors : capabilities?.actions?.execute; +export const hasExecuteActionsCapability = (capabilities: Capabilities, isEdrAction?: boolean) => + isEdrAction ? capabilities?.actions?.executeEdr : capabilities?.actions?.execute; export const hasDeleteActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.delete; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx index d82a114531909..508546e5529d9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx @@ -29,7 +29,7 @@ import { hasExecuteActionsCapability } from '../../../lib/capabilities'; const FlyoutHeaderComponent: React.FC<{ isExperimental?: boolean; - isEdrConnectorType?: boolean; + isEdrActionType?: boolean; isPreconfigured: boolean; connectorName: string; connectorTypeDesc: string; @@ -39,7 +39,7 @@ const FlyoutHeaderComponent: React.FC<{ }> = ({ icon, isExperimental = false, - isEdrConnectorType = false, + isEdrActionType = false, isPreconfigured, connectorName, connectorTypeDesc, @@ -51,7 +51,7 @@ const FlyoutHeaderComponent: React.FC<{ } = useKibana().services; const { euiTheme } = useEuiTheme(); - const canExecute = hasExecuteActionsCapability(capabilities, isEdrConnectorType); + const canExecute = hasExecuteActionsCapability(capabilities, isEdrActionType); const setConfigurationTab = useCallback(() => { setTab(EditConnectorTabs.Configuration); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index a06876904493a..21ff098f81b93 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -321,7 +321,7 @@ const EditConnectorFlyoutComponent: React.FC = ({ selectedTab={selectedTab} icon={actionTypeModel?.iconClass} isExperimental={actionTypeModel?.isExperimental} - isEdrConnectorType={actionTypeModel?.isEdrConnectorType} + isEdrActionType={actionTypeModel?.isEdrActionType} /> {selectedTab === EditConnectorTabs.Configuration && renderConfigurationTab()} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index c39a0acc80821..64eece536cfc8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -341,7 +341,7 @@ const ActionsConnectorsList = ({ !!( hasExecuteActionsCapability( capabilities, - actionTypesIndex && actionTypesIndex[item.actionTypeId].isEdrConnectorType + actionTypesIndex && actionTypesIndex[item.actionTypeId].isEdrActionType ) && actionTypesIndex && actionTypesIndex[item.actionTypeId] From 96ccb6db66547cd837dada3217f2d4024cf9eb28 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 23 Oct 2024 12:06:38 -0700 Subject: [PATCH 04/15] Fix boolean --- x-pack/plugins/actions/server/action_type_registry.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index 2f9f3e7872cdc..3b0950d47f523 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -121,7 +121,7 @@ export class ActionTypeRegistry { ): string[] { const actionType = this.actionTypes.get(actionTypeId); - if (!actionType?.isSystemActionType || !actionType?.isEdrActionType) { + if (!actionType?.isSystemActionType && !actionType?.isEdrActionType) { return []; } @@ -176,7 +176,8 @@ export class ActionTypeRegistry { } if ( - (!actionType.isSystemActionType || !actionType.isEdrActionType) && + !actionType.isSystemActionType && + !actionType.isEdrActionType && actionType.getKibanaPrivileges ) { throw new Error( From c27495144ef87815ab0e8ee00489d6f85e1b5c01 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 23 Oct 2024 12:41:19 -0700 Subject: [PATCH 05/15] Removing changes from email connector --- x-pack/plugins/actions/server/sub_action_framework/register.ts | 1 + x-pack/plugins/actions/server/sub_action_framework/types.ts | 1 + .../stack_connectors/server/connector_types/email/index.ts | 3 --- .../server/connector_types/sentinelone/index.ts | 3 +++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/actions/server/sub_action_framework/register.ts b/x-pack/plugins/actions/server/sub_action_framework/register.ts index 04e7f0d9ea417..06b9026716f9e 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/register.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/register.ts @@ -41,6 +41,7 @@ export const register = { getService: (params: ServiceParams) => SubActionConnector; renderParameterTemplates?: RenderParameterTemplates; isSystemActionType?: boolean; + isEdrActionType?: boolean; getKibanaPrivileges?: (args?: { params?: { subAction: string; subActionParams: Record }; }) => string[]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts index d4401f182c4fc..3a1d01732eb7d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts @@ -22,7 +22,6 @@ import { UptimeConnectorFeatureId, SecurityConnectorFeatureId, } from '@kbn/actions-plugin/common/connector_feature_config'; -import { CONNECTORS_EDR_EXECUTE_PRIVILEGE } from '@kbn/actions-plugin/server/feature'; import { withoutMustacheTemplate } from '@kbn/actions-plugin/common'; import { renderMustacheObject, @@ -249,8 +248,6 @@ export function getConnectorType(params: GetConnectorTypeParams): EmailConnector }, renderParameterTemplates, executor: curry(executor)({ publicBaseUrl }), - isEdrActionType: true, - getKibanaPrivileges: () => [CONNECTORS_EDR_EXECUTE_PRIVILEGE], }; } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts index 849d54e276e11..be78239c535fb 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts @@ -11,6 +11,7 @@ import { } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { SecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; import { urlAllowListValidator } from '@kbn/actions-plugin/server'; +import { CONNECTORS_EDR_EXECUTE_PRIVILEGE } from '@kbn/actions-plugin/server/feature'; import { SENTINELONE_CONNECTOR_ID, SENTINELONE_TITLE } from '../../../common/sentinelone/constants'; import { SentinelOneConfigSchema, @@ -35,4 +36,6 @@ export const getSentinelOneConnectorType = (): SubActionConnectorType< supportedFeatureIds: [SecurityConnectorFeatureId], minimumLicenseRequired: 'enterprise' as const, renderParameterTemplates, + isEdrActionType: true, + getKibanaPrivileges: () => [CONNECTORS_EDR_EXECUTE_PRIVILEGE], }); From 4f29da89d3b6af136c9c366493cccc4f09f04072 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 23 Oct 2024 12:55:32 -0700 Subject: [PATCH 06/15] Updating canExecute --- .../components/actions_connectors_list.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 64eece536cfc8..5a401068b6024 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -339,12 +339,12 @@ const ActionsConnectorsList = ({ Date: Tue, 19 Nov 2024 09:21:39 -0800 Subject: [PATCH 07/15] Fixing a bad change from merge conflicts --- .../actions/server/authorization/actions_authorization.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/actions/server/authorization/actions_authorization.ts b/x-pack/plugins/actions/server/authorization/actions_authorization.ts index 650c84f5b6e55..26400a31c59eb 100644 --- a/x-pack/plugins/actions/server/authorization/actions_authorization.ts +++ b/x-pack/plugins/actions/server/authorization/actions_authorization.ts @@ -12,8 +12,6 @@ import { ACTION_SAVED_OBJECT_TYPE, ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, } from '../constants/saved_objects'; -import { AuthorizationMode } from './get_authorization_mode_by_source'; -import { isBidirectionalConnectorType } from '../lib/bidirectional_connectors'; export interface ConstructorOptions { request: KibanaRequest; From 3e5f43f58ff21e276ef47b9656e76b38411a917b Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Fri, 22 Nov 2024 11:54:49 -0800 Subject: [PATCH 08/15] Update EDR connectors to only allow testing for one sub action --- .../actions/server/action_type_registry.ts | 13 +++- .../connector/methods/execute/execute.ts | 2 +- x-pack/plugins/actions/server/feature.ts | 29 +------ x-pack/plugins/actions/server/index.ts | 1 + .../actions/server/lib/action_executor.ts | 11 ++- .../lib/get_action_kibana_privileges.ts | 10 ++- .../server/sub_action_framework/types.ts | 2 + x-pack/plugins/actions/server/types.ts | 7 +- .../sentinelone/sentinelone.ts | 2 +- .../sentinelone/sentinelone_params.tsx | 75 +++++++++++++++++++ .../sentinelone/translations.ts | 7 ++ .../connector_types/sentinelone/index.ts | 11 ++- .../public/application/lib/capabilities.ts | 4 +- .../edit_connector_flyout/header.tsx | 4 +- .../edit_connector_flyout/index.tsx | 1 - .../components/actions_connectors_list.tsx | 7 +- 16 files changed, 133 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone_params.tsx diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index 3b0950d47f523..b10ef2edee2d1 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -11,7 +11,12 @@ import { RunContext, TaskManagerSetupContract, TaskCost } from '@kbn/task-manage import { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; import { ActionType as CommonActionType, areValidFeatures } from '../common'; import { ActionsConfigurationUtilities } from './actions_config'; -import { getActionTypeFeatureUsageName, TaskRunnerFactory, ILicenseState } from './lib'; +import { + getActionTypeFeatureUsageName, + TaskRunnerFactory, + ILicenseState, + ActionExecutionSourceType, +} from './lib'; import { ActionType, InMemoryConnector, @@ -117,15 +122,15 @@ export class ActionTypeRegistry { */ public getActionKibanaPrivileges( actionTypeId: string, - params?: Params + params?: Params, + source?: ActionExecutionSourceType ): string[] { const actionType = this.actionTypes.get(actionTypeId); if (!actionType?.isSystemActionType && !actionType?.isEdrActionType) { return []; } - - return actionType?.getKibanaPrivileges?.({ params }) ?? []; + return actionType?.getKibanaPrivileges?.({ params, source }) ?? []; } /** diff --git a/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts b/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts index 48b4cde848098..99302f7ff3020 100644 --- a/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts +++ b/x-pack/plugins/actions/server/application/connector/methods/execute/execute.ts @@ -20,7 +20,7 @@ export async function execute( ): Promise> { const log = context.logger; const { actionId, params, source, relatedSavedObjects } = connectorExecuteParams; - const additionalPrivileges = getActionKibanaPrivileges(context, actionId, params); + const additionalPrivileges = getActionKibanaPrivileges(context, actionId, params, source?.type); let actionTypeId: string | undefined; try { diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index 40a408863a5c5..5174ccfbeeae8 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -40,7 +40,7 @@ export const ACTIONS_FEATURE = { privileges: { all: { app: [], - api: [CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG, CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG], + api: [CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG], catalogue: [], management: { insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], @@ -70,31 +70,4 @@ export const ACTIONS_FEATURE = { ui: ['show', 'execute'], }, }, - subFeatures: [ - { - name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureName', { - defaultMessage: 'EDR Connectors', - }), - privilegeGroups: [ - { - groupType: 'independent', - privileges: [ - { - api: [CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG], - id: 'executeEdrConnectors', - name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureDetails', { - defaultMessage: 'Execute advanced EDR connectors', - }), - includeIn: 'all', - savedObject: { - all: [ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, CONNECTOR_TOKEN_SAVED_OBJECT_TYPE], - read: [ACTION_SAVED_OBJECT_TYPE], - }, - ui: ['executeEdr'], - }, - ], - }, - ], - }, - ], }; diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index d391911ff0fc3..5cfe1a9211297 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -53,3 +53,4 @@ export const config: PluginConfigDescriptor = { }; export { urlAllowListValidator } from './sub_action_framework/helpers'; +export { ActionExecutionSourceType } from './lib/action_execution_source'; diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 04cd81ef976de..c8e0553d23b67 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -48,7 +48,7 @@ import { ValidatorServices, } from '../types'; import { EVENT_LOG_ACTIONS } from '../constants/event_log'; -import { ActionExecutionSource } from './action_execution_source'; +import { ActionExecutionSource, ActionExecutionSourceType } from './action_execution_source'; import { RelatedSavedObjects } from './related_saved_objects'; import { createActionEventLogRecordObject } from './create_action_event_log_record_object'; import { ActionExecutionError, ActionExecutionErrorReason } from './errors/action_execution_error'; @@ -170,6 +170,7 @@ export class ActionExecutor { actionTypeId: connectorTypeId, actionTypeRegistry, authorization, + source: source?.type, }); }, executeLabel: `execute_action`, @@ -722,6 +723,7 @@ interface EnsureAuthorizedToExecuteOpts { params: Record; actionTypeRegistry: ActionTypeRegistryContract; authorization: ActionsAuthorization; + source?: ActionExecutionSourceType; } const ensureAuthorizedToExecute = async ({ @@ -730,9 +732,14 @@ const ensureAuthorizedToExecute = async ({ params, actionTypeRegistry, authorization, + source, }: EnsureAuthorizedToExecuteOpts) => { try { - const additionalPrivileges = actionTypeRegistry.getActionKibanaPrivileges(actionTypeId, params); + const additionalPrivileges = actionTypeRegistry.getActionKibanaPrivileges( + actionTypeId, + params, + source + ); await authorization.ensureAuthorized({ operation: 'execute', diff --git a/x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts b/x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts index ec5336d24a925..2e27a72750bdc 100644 --- a/x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts +++ b/x-pack/plugins/actions/server/lib/get_action_kibana_privileges.ts @@ -6,19 +6,25 @@ */ import { ActionsClientContext } from '../actions_client'; +import { ActionExecutionSourceType } from './action_execution_source'; import { ExecuteOptions } from './action_executor'; export function getActionKibanaPrivileges( context: ActionsClientContext, connectorId: string, - params?: ExecuteOptions['params'] + params?: ExecuteOptions['params'], + source?: ActionExecutionSourceType ) { const inMemoryConnector = context.inMemoryConnectors.find( (connector) => connector.id === connectorId ); const additionalPrivileges = inMemoryConnector - ? context.actionTypeRegistry.getActionKibanaPrivileges(inMemoryConnector.actionTypeId, params) + ? context.actionTypeRegistry.getActionKibanaPrivileges( + inMemoryConnector.actionTypeId, + params, + source + ) : []; return additionalPrivileges; diff --git a/x-pack/plugins/actions/server/sub_action_framework/types.ts b/x-pack/plugins/actions/server/sub_action_framework/types.ts index 89a8e02770845..98ad9046704b0 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/types.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/types.ts @@ -20,6 +20,7 @@ import type { } from '../types'; import type { SubActionConnector } from './sub_action_connector'; import type { HookServices } from '../types'; +import { ActionExecutionSourceType } from '../lib'; export interface ServiceParams { /** @@ -122,6 +123,7 @@ export interface SubActionConnectorType { isEdrActionType?: boolean; getKibanaPrivileges?: (args?: { params?: { subAction: string; subActionParams: Record }; + source?: ActionExecutionSourceType; }) => string[]; preSaveHook?: (params: PreSaveConnectorHookParams) => Promise; postSaveHook?: (params: PostSaveConnectorHookParams) => Promise; diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 5bda49413ecd9..f24eb1b5d3ee2 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -41,7 +41,7 @@ export type ActionTypeParams = Record; export type ConnectorTokenClientContract = PublicMethodsOf; import { Connector, ConnectorWithExtraFindData } from './application/connector/types'; -import type { ActionExecutionSource } from './lib'; +import type { ActionExecutionSource, ActionExecutionSourceType } from './lib'; export { ActionExecutionSourceType } from './lib'; import { ConnectorUsageCollector } from './usage'; export { ConnectorUsageCollector } from './usage'; @@ -211,7 +211,10 @@ export interface ActionType< * It only works with system actions and only when executing an action. * For all other scenarios they will be ignored */ - getKibanaPrivileges?: (args?: { params?: Params }) => string[]; + getKibanaPrivileges?: (args?: { + params?: Params; + source?: ActionExecutionSourceType; + }) => string[]; renderParameterTemplates?: RenderParameterTemplates; executor: ExecutorType; getService?: (params: ServiceParams) => SubActionConnector; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone.ts b/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone.ts index 2344833ceb0c7..a65fc6a4f011c 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone.ts @@ -60,6 +60,6 @@ export function getConnectorType(): ConnectorTypeModel< return { errors }; }, actionConnectorFields: lazy(() => import('./sentinelone_connector')), - actionParamsFields: lazy(() => import('./sentinelone_params_empty')), + actionParamsFields: lazy(() => import('./sentinelone_params')), }; } diff --git a/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone_params.tsx new file mode 100644 index 0000000000000..fc0be9ca5de3c --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/sentinelone_params.tsx @@ -0,0 +1,75 @@ +/* + * 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 React, { useCallback, useState, useEffect } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSuperSelect } from '@elastic/eui'; +import { ActionParamsProps } from '@kbn/triggers-actions-ui-plugin/public'; +import { SUB_ACTION } from '../../../common/sentinelone/constants'; +import type { SentinelOneActionParams } from '../../../common/sentinelone/types'; +import type { SentinelOneExecuteSubActionParams } from './types'; +import * as i18n from './translations'; + +const SentinelOneParamsFields: React.FunctionComponent< + ActionParamsProps +> = ({ actionConnector, actionParams, editAction, index, executionMode, errors, ...rest }) => { + const { subAction, subActionParams } = actionParams; + + const [subActionValue, setSubActionValue] = useState( + subAction ?? SUB_ACTION.GET_AGENTS + ); + const setDefaultValues = async () => { + editSubActionParams({}); + editAction('subAction', subActionValue, index); + }; + useEffect(() => { + setDefaultValues(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const editSubActionParams = useCallback( + (params: Partial) => { + editAction('subActionParams', { ...subActionParams, ...params }, index); + }, + [editAction, index, subActionParams] + ); + + const actionTypeOptions = [ + { + value: SUB_ACTION.GET_AGENTS, + inputDisplay: i18n.GET_AGENT_ACTION_LABEL, + }, + ]; + + const handleEditSubAction = useCallback( + (payload) => { + if (subAction !== payload) { + editSubActionParams({}); + editAction('subAction', payload, index); + setSubActionValue(payload); + } + }, + [editAction, editSubActionParams, index, subAction] + ); + + return ( + + + + + + + + ); +}; + +// eslint-disable-next-line import/no-default-export +export { SentinelOneParamsFields as default }; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/translations.ts b/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/translations.ts index a5b9a274857c3..6bde942d8ee28 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/translations.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/sentinelone/translations.ts @@ -73,6 +73,13 @@ export const RELEASE_AGENT_ACTION_LABEL = i18n.translate( } ); +export const GET_AGENT_ACTION_LABEL = i18n.translate( + 'xpack.stackConnectors.security.sentinelone.params.getAgentActionLabel', + { + defaultMessage: 'Get agent details', + } +); + export const AGENTS_FIELD_LABEL = i18n.translate( 'xpack.stackConnectors.security.sentinelone.params.agentsFieldLabel', { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts index be78239c535fb..5f908d069aef7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts @@ -10,9 +10,11 @@ import { ValidatorType, } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { SecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; -import { urlAllowListValidator } from '@kbn/actions-plugin/server'; +import { urlAllowListValidator, ActionExecutionSourceType } from '@kbn/actions-plugin/server'; import { CONNECTORS_EDR_EXECUTE_PRIVILEGE } from '@kbn/actions-plugin/server/feature'; import { SENTINELONE_CONNECTOR_ID, SENTINELONE_TITLE } from '../../../common/sentinelone/constants'; +import { SUB_ACTION } from '../../../common/sentinelone/constants'; + import { SentinelOneConfigSchema, SentinelOneSecretsSchema, @@ -37,5 +39,10 @@ export const getSentinelOneConnectorType = (): SubActionConnectorType< minimumLicenseRequired: 'enterprise' as const, renderParameterTemplates, isEdrActionType: true, - getKibanaPrivileges: () => [CONNECTORS_EDR_EXECUTE_PRIVILEGE], + getKibanaPrivileges: (args) => { + return args?.source === ActionExecutionSourceType.HTTP_REQUEST && + args?.params?.subAction !== SUB_ACTION.GET_AGENTS + ? [CONNECTORS_EDR_EXECUTE_PRIVILEGE] + : []; + }, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts index 1ea5774845dd1..1c31cb30aaaf9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts @@ -18,8 +18,8 @@ type Capabilities = Record; export const hasShowActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.show; export const hasSaveActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.save; -export const hasExecuteActionsCapability = (capabilities: Capabilities, isEdrAction?: boolean) => - isEdrAction ? capabilities?.actions?.executeEdr : capabilities?.actions?.execute; +export const hasExecuteActionsCapability = (capabilities: Capabilities) => + capabilities?.actions?.execute; export const hasDeleteActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.delete; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx index 508546e5529d9..9bce14109b605 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx @@ -29,7 +29,6 @@ import { hasExecuteActionsCapability } from '../../../lib/capabilities'; const FlyoutHeaderComponent: React.FC<{ isExperimental?: boolean; - isEdrActionType?: boolean; isPreconfigured: boolean; connectorName: string; connectorTypeDesc: string; @@ -39,7 +38,6 @@ const FlyoutHeaderComponent: React.FC<{ }> = ({ icon, isExperimental = false, - isEdrActionType = false, isPreconfigured, connectorName, connectorTypeDesc, @@ -51,7 +49,7 @@ const FlyoutHeaderComponent: React.FC<{ } = useKibana().services; const { euiTheme } = useEuiTheme(); - const canExecute = hasExecuteActionsCapability(capabilities, isEdrActionType); + const canExecute = hasExecuteActionsCapability(capabilities); const setConfigurationTab = useCallback(() => { setTab(EditConnectorTabs.Configuration); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index 21ff098f81b93..8ae7e11fb2c0e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -321,7 +321,6 @@ const EditConnectorFlyoutComponent: React.FC = ({ selectedTab={selectedTab} icon={actionTypeModel?.iconClass} isExperimental={actionTypeModel?.isExperimental} - isEdrActionType={actionTypeModel?.isEdrActionType} /> {selectedTab === EditConnectorTabs.Configuration && renderConfigurationTab()} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index ab551c23d54d7..32942167a200a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -339,12 +339,9 @@ const ActionsConnectorsList = ({ Date: Tue, 3 Dec 2024 09:30:07 -0800 Subject: [PATCH 09/15] Adding validation to rule creation --- .../common/hooks/use_load_connector_types.ts | 5 ++- .../src/rule_form/create_rule_form.tsx | 3 ++ .../src/rule_form/edit_rule_form.tsx | 11 +++++- .../rule_form/hooks/use_load_dependencies.ts | 3 ++ .../common/connector_feature_config.ts | 15 ++++++++ .../actions/server/action_type_registry.ts | 37 ++++++++----------- .../server/lib/bidirectional_connectors.ts | 15 -------- .../rule/methods/update/update_rule.ts | 2 +- .../rules_client/lib/validate_actions.ts | 25 +++++++++++++ .../connector_types/sentinelone/index.ts | 4 +- 10 files changed, 77 insertions(+), 43 deletions(-) delete mode 100644 x-pack/plugins/actions/server/lib/bidirectional_connectors.ts diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.ts index 2810758a57f0f..4bd9ff5e928be 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.ts @@ -15,13 +15,14 @@ export interface UseLoadConnectorTypesProps { http: HttpStart; includeSystemActions?: boolean; enabled?: boolean; + featureId?: string; } export const useLoadConnectorTypes = (props: UseLoadConnectorTypesProps) => { - const { http, includeSystemActions, enabled = true } = props; + const { http, includeSystemActions, enabled = true, featureId } = props; const queryFn = () => { - return fetchConnectorTypes({ http, includeSystemActions }); + return fetchConnectorTypes({ http, includeSystemActions, featureId }); }; const { data, isLoading, isFetching, isInitialLoading } = useQuery({ diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx index 4399dc5239ec7..2b899d8c9953d 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx @@ -45,6 +45,7 @@ export interface CreateRuleFormProps { showMustacheAutocompleteSwitch?: boolean; onCancel?: () => void; onSubmit?: (ruleId: string) => void; + connectorFeatureId?: string; } export const CreateRuleForm = (props: CreateRuleFormProps) => { @@ -58,6 +59,7 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => { shouldUseRuleProducer = false, canShowConsumerSelection = true, showMustacheAutocompleteSwitch = false, + connectorFeatureId = 'alerting', onCancel, onSubmit, } = props; @@ -107,6 +109,7 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => { consumer, validConsumers, filteredRuleTypes, + connectorFeatureId, }); const onSave = useCallback( diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx index 917fc87420f9a..9a7b677fa9e18 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx @@ -33,10 +33,18 @@ export interface EditRuleFormProps { showMustacheAutocompleteSwitch?: boolean; onCancel?: () => void; onSubmit?: (ruleId: string) => void; + connectorFeatureId?: string; } export const EditRuleForm = (props: EditRuleFormProps) => { - const { id, plugins, showMustacheAutocompleteSwitch = false, onCancel, onSubmit } = props; + const { + id, + plugins, + showMustacheAutocompleteSwitch = false, + onCancel, + onSubmit, + connectorFeatureId = 'alerting', + } = props; const { http, notifications, docLinks, ruleTypeRegistry, i18n, theme, application } = plugins; const { toasts } = notifications; @@ -80,6 +88,7 @@ export const EditRuleForm = (props: EditRuleFormProps) => { capabilities: plugins.application.capabilities, ruleTypeRegistry, id, + connectorFeatureId, }); const onSave = useCallback( diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.ts b/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.ts index 9fb0f173b9d21..b4a7d3bb777b0 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.ts +++ b/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.ts @@ -35,6 +35,7 @@ export interface UseLoadDependencies { ruleTypeId?: string; validConsumers?: RuleCreationValidConsumer[]; filteredRuleTypes?: string[]; + connectorFeatureId?: string; } export const useLoadDependencies = (props: UseLoadDependencies) => { @@ -46,6 +47,7 @@ export const useLoadDependencies = (props: UseLoadDependencies) => { ruleTypeId, capabilities, filteredRuleTypes = [], + connectorFeatureId, } = props; const canReadConnectors = !!capabilities.actions?.show; @@ -113,6 +115,7 @@ export const useLoadDependencies = (props: UseLoadDependencies) => { http, includeSystemActions: true, enabled: canReadConnectors, + featureId: connectorFeatureId, }); const { diff --git a/x-pack/plugins/actions/common/connector_feature_config.ts b/x-pack/plugins/actions/common/connector_feature_config.ts index cffa4c433b8f7..e54f584d5868a 100644 --- a/x-pack/plugins/actions/common/connector_feature_config.ts +++ b/x-pack/plugins/actions/common/connector_feature_config.ts @@ -28,6 +28,14 @@ export const SecurityConnectorFeatureId = 'siem'; export const GenerativeAIForSecurityConnectorFeatureId = 'generativeAIForSecurity'; export const GenerativeAIForObservabilityConnectorFeatureId = 'generativeAIForObservability'; export const GenerativeAIForSearchPlaygroundConnectorFeatureId = 'generativeAIForSearchPlayground'; +export const EdrForSecurityConnectorFeatureId = 'edrForSecurity'; + +const compatibilityEdrForSecurity = i18n.translate( + 'xpack.actions.availableConnectorFeatures.compatibility.edrForSecurity', + { + defaultMessage: 'EDR for Security', + } +); const compatibilityGenerativeAIForSecurity = i18n.translate( 'xpack.actions.availableConnectorFeatures.compatibility.generativeAIForSecurity', @@ -120,6 +128,12 @@ export const GenerativeAIForSearchPlaygroundFeature: ConnectorFeatureConfig = { compatibility: compatibilityGenerativeAIForSearchPlayground, }; +export const EdrForSecurityFeature: ConnectorFeatureConfig = { + id: EdrForSecurityConnectorFeatureId, + name: compatibilityEdrForSecurity, + compatibility: compatibilityEdrForSecurity, +}; + const AllAvailableConnectorFeatures = { [AlertingConnectorFeature.id]: AlertingConnectorFeature, [CasesConnectorFeature.id]: CasesConnectorFeature, @@ -128,6 +142,7 @@ const AllAvailableConnectorFeatures = { [GenerativeAIForSecurityFeature.id]: GenerativeAIForSecurityFeature, [GenerativeAIForObservabilityFeature.id]: GenerativeAIForObservabilityFeature, [GenerativeAIForSearchPlaygroundFeature.id]: GenerativeAIForSearchPlaygroundFeature, + [EdrForSecurityFeature.id]: EdrForSecurityFeature, }; export function areValidFeatures(ids: string[]) { diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index b10ef2edee2d1..ca70f25feb8bb 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -24,7 +24,6 @@ import { ActionTypeSecrets, ActionTypeParams, } from './types'; -import { isBidirectionalConnectorType } from './lib/bidirectional_connectors'; export interface ActionTypeRegistryOpts { licensing: LicensingPluginSetup; @@ -242,27 +241,21 @@ export class ActionTypeRegistry { * Returns a list of registered action types [{ id, name, enabled }], filtered by featureId if provided. */ public list(featureId?: string): CommonActionType[] { - return ( - Array.from(this.actionTypes) - .filter(([_, actionType]) => - featureId ? actionType.supportedFeatureIds.includes(featureId) : true - ) - // Temporarily don't return SentinelOne and Crowdstrike connector for Security Solution Rule Actions - .filter(([actionTypeId]) => - featureId ? !isBidirectionalConnectorType(actionTypeId) : true - ) - .map(([actionTypeId, actionType]) => ({ - id: actionTypeId, - name: actionType.name, - minimumLicenseRequired: actionType.minimumLicenseRequired, - enabled: this.isActionTypeEnabled(actionTypeId), - enabledInConfig: this.actionsConfigUtils.isActionTypeEnabled(actionTypeId), - enabledInLicense: !!this.licenseState.isLicenseValidForActionType(actionType).isValid, - supportedFeatureIds: actionType.supportedFeatureIds, - isSystemActionType: !!actionType.isSystemActionType, - isEdrActionType: !!actionType.isEdrActionType, - })) - ); + return Array.from(this.actionTypes) + .filter(([_, actionType]) => { + return featureId ? actionType.supportedFeatureIds.includes(featureId) : true; + }) + .map(([actionTypeId, actionType]) => ({ + id: actionTypeId, + name: actionType.name, + minimumLicenseRequired: actionType.minimumLicenseRequired, + enabled: this.isActionTypeEnabled(actionTypeId), + enabledInConfig: this.actionsConfigUtils.isActionTypeEnabled(actionTypeId), + enabledInLicense: !!this.licenseState.isLicenseValidForActionType(actionType).isValid, + supportedFeatureIds: actionType.supportedFeatureIds, + isSystemActionType: !!actionType.isSystemActionType, + isEdrActionType: !!actionType.isEdrActionType, + })); } /** diff --git a/x-pack/plugins/actions/server/lib/bidirectional_connectors.ts b/x-pack/plugins/actions/server/lib/bidirectional_connectors.ts deleted file mode 100644 index 49d33f9d016c3..0000000000000 --- a/x-pack/plugins/actions/server/lib/bidirectional_connectors.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 BIDIRECTIONAL_CONNECTOR_TYPES = ['.sentinelone', '.crowdstrike']; -export const isBidirectionalConnectorType = (type: string | undefined) => { - if (!type) { - return false; - } - - return BIDIRECTIONAL_CONNECTOR_TYPES.includes(type); -}; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts index 25759e8e06c70..65e1c21702f3c 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts @@ -211,7 +211,7 @@ async function updateWithOCC( const actionsClient = await context.getActionsClient(); const validatedRuleTypeParams = validateRuleTypeParams(data.params, ruleType.validate.params); - await validateActions(context, ruleType, data, allowMissingConnectorSecrets); + await validateActions(context, ruleType, data, consumer, allowMissingConnectorSecrets); await validateAndAuthorizeSystemActions({ actionsClient, actionsAuthorization: context.actionsAuthorization, diff --git a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts index 4f5be980bae89..de890eaff6b2c 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts @@ -24,6 +24,7 @@ export async function validateActions( context: RulesClientContext, ruleType: UntypedNormalizedRuleType, data: ValidateActionsData, + consumer: string, allowMissingConnectorSecrets?: boolean ): Promise { const { actions, notifyWhen, throttle, systemActions = [] } = data; @@ -76,6 +77,30 @@ export async function validateActions( ); } } + + // check for invalid EDR actions + const allConnectorTypes = await actionsClient.listTypes({}); + const edrConnectorTypes = allConnectorTypes.filter((type) => type.isEdrActionType); + const edrConnectorTypesMap = Object.fromEntries(edrConnectorTypes.map((type) => [type.id, type])); + + const edrConnectorTypeIds = Object.keys(edrConnectorTypesMap); + const actionTypeIds = new Set(actionResults.map((result) => result.actionTypeId)); + const edrActionTypeIds = edrConnectorTypeIds.filter((id) => actionTypeIds.has(id)); + + const hasInvalidEdrActions = + edrActionTypeIds.length > 0 && + edrActionTypeIds.some( + (actionId) => !edrConnectorTypesMap[actionId]?.supportedFeatureIds.includes(consumer) + ); + + if (hasInvalidEdrActions) { + errors.push( + i18n.translate('xpack.alerting.rulesClient.validateActions.edrConnector', { + defaultMessage: 'Invalid EDR connectors.', + }) + ); + } + // check for actions with invalid action groups const { actionGroups: alertTypeActionGroups } = ruleType; const usedAlertActionGroups = actions.map((action) => action.group); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts index 5f908d069aef7..3ab5376df74cc 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts @@ -9,7 +9,7 @@ import { SubActionConnectorType, ValidatorType, } from '@kbn/actions-plugin/server/sub_action_framework/types'; -import { SecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; +import { EdrForSecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; import { urlAllowListValidator, ActionExecutionSourceType } from '@kbn/actions-plugin/server'; import { CONNECTORS_EDR_EXECUTE_PRIVILEGE } from '@kbn/actions-plugin/server/feature'; import { SENTINELONE_CONNECTOR_ID, SENTINELONE_TITLE } from '../../../common/sentinelone/constants'; @@ -35,7 +35,7 @@ export const getSentinelOneConnectorType = (): SubActionConnectorType< secrets: SentinelOneSecretsSchema, }, validators: [{ type: ValidatorType.CONFIG, validator: urlAllowListValidator('url') }], - supportedFeatureIds: [SecurityConnectorFeatureId], + supportedFeatureIds: [EdrForSecurityConnectorFeatureId], minimumLicenseRequired: 'enterprise' as const, renderParameterTemplates, isEdrActionType: true, From 613381acfc80d0eb226b8996d09c420ed2794c3b Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Tue, 3 Dec 2024 09:35:53 -0800 Subject: [PATCH 10/15] Removing changes from merge conflicts --- .../kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx | 2 -- packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx | 1 - 2 files changed, 3 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx index 4b228450d8e75..b0d95a7d5c2c9 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx @@ -46,7 +46,6 @@ export interface CreateRuleFormProps { showMustacheAutocompleteSwitch?: boolean; onCancel?: () => void; onSubmit?: (ruleId: string) => void; - connectorFeatureId?: string; } export const CreateRuleForm = (props: CreateRuleFormProps) => { @@ -61,7 +60,6 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => { shouldUseRuleProducer = false, canShowConsumerSelection = true, showMustacheAutocompleteSwitch = false, - connectorFeatureId = 'alerting', onCancel, onSubmit, } = props; diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx index 0bbe89d547e73..ace31d1b7b6fb 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/edit_rule_form.tsx @@ -34,7 +34,6 @@ export interface EditRuleFormProps { connectorFeatureId?: string; onCancel?: () => void; onSubmit?: (ruleId: string) => void; - connectorFeatureId?: string; } export const EditRuleForm = (props: EditRuleFormProps) => { From 6403e6b2bdd74818ff9bdf9607499a09a58fec90 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Tue, 3 Dec 2024 14:51:30 -0800 Subject: [PATCH 11/15] Adding api key info to the event log --- .../src/authentication/authenticated_user.ts | 17 ++++++++++++++ .../actions/server/lib/action_executor.ts | 1 + .../rules_client/lib/validate_actions.ts | 22 +++++++------------ .../plugins/event_log/generated/mappings.json | 10 +++++++++ x-pack/plugins/event_log/generated/schemas.ts | 6 +++++ x-pack/plugins/event_log/scripts/mappings.js | 11 ++++++++++ 6 files changed, 53 insertions(+), 14 deletions(-) diff --git a/packages/core/security/core-security-common/src/authentication/authenticated_user.ts b/packages/core/security/core-security-common/src/authentication/authenticated_user.ts index 4aa871125052b..5d51d49e65a7a 100644 --- a/packages/core/security/core-security-common/src/authentication/authenticated_user.ts +++ b/packages/core/security/core-security-common/src/authentication/authenticated_user.ts @@ -25,6 +25,18 @@ export interface UserRealm { type: string; } +export interface ApiKey { + /** + * Name of the API key. + */ + name: string; + + /** + * The ID of the API key. + */ + id: string; +} + /** * Represents the currently authenticated user. */ @@ -60,4 +72,9 @@ export interface AuthenticatedUser extends User { * User profile ID of this user. */ profile_uid?: string; + + /** + * Metadata of the API key that was used to authenticate the user. + */ + api_key?: ApiKey; } diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 5260d5f44a030..f2969f78f4079 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -552,6 +552,7 @@ export class ActionExecutor { event.user = event.user || {}; event.user.name = currentUser?.username; event.user.id = currentUser?.profile_uid; + event.api_key = currentUser?.api_key; set( event, 'kibana.action.execution.usage.request_body_bytes', diff --git a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts index de890eaff6b2c..e9885e7ef730e 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts @@ -78,22 +78,16 @@ export async function validateActions( } } - // check for invalid EDR actions + // check for invalid EDR connectors const allConnectorTypes = await actionsClient.listTypes({}); - const edrConnectorTypes = allConnectorTypes.filter((type) => type.isEdrActionType); - const edrConnectorTypesMap = Object.fromEntries(edrConnectorTypes.map((type) => [type.id, type])); - - const edrConnectorTypeIds = Object.keys(edrConnectorTypesMap); - const actionTypeIds = new Set(actionResults.map((result) => result.actionTypeId)); - const edrActionTypeIds = edrConnectorTypeIds.filter((id) => actionTypeIds.has(id)); - - const hasInvalidEdrActions = - edrActionTypeIds.length > 0 && - edrActionTypeIds.some( - (actionId) => !edrConnectorTypesMap[actionId]?.supportedFeatureIds.includes(consumer) - ); + const edrConnectorTypeIds = new Set( + allConnectorTypes.filter((type) => type.isEdrActionType).map((type) => type.id) + ); + const edrActionTypeIds = actionResults + .map((result) => result.actionTypeId) + .filter((id) => edrConnectorTypeIds.has(id)); - if (hasInvalidEdrActions) { + if (edrActionTypeIds.length > 0) { errors.push( i18n.translate('xpack.alerting.rulesClient.validateActions.edrConnector', { defaultMessage: 'Invalid EDR connectors.', diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index 5fc8128baa7ae..9b337e5a06198 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -525,6 +525,16 @@ } } } + }, + "api_key": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + } + } } } } \ No newline at end of file diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index 7542d6db5213a..feb4a7a8e5423 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -239,6 +239,12 @@ export const EventSchema = schema.maybe( ), }) ), + api_key: schema.maybe( + schema.object({ + id: ecsString(), + name: ecsString(), + }) + ), }) ); diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index 770f9e6d45f9a..98ce3fb192c5a 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -301,6 +301,16 @@ exports.EcsCustomPropertyMappings = { }, }, }, + api_key: { + properties: { + id: { + type: 'keyword', + }, + name: { + type: 'keyword', + }, + }, + }, }; /** @@ -320,6 +330,7 @@ exports.EcsPropertiesToGenerate = [ 'user.name', 'user.id', 'kibana', + 'api_key', ]; /** From a2d20798f5c198cc7a4181b20e565d0c67a63ca6 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 4 Dec 2024 08:55:44 -0800 Subject: [PATCH 12/15] Removing some changes that arent needed --- .../server/authorization/actions_authorization.test.ts | 4 ++-- x-pack/plugins/actions/server/feature.ts | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts b/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts index 4f9743893afe8..7755071e69c24 100644 --- a/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts +++ b/x-pack/plugins/actions/server/authorization/actions_authorization.test.ts @@ -13,7 +13,7 @@ import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, } from '../constants/saved_objects'; import { - CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG, + CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG, CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG, } from '../feature'; import { forEach } from 'lodash'; @@ -22,7 +22,7 @@ const request = {} as KibanaRequest; const mockAuthorizationAction = (type: string, operation: string) => `${type}/${operation}`; const BASIC_EXECUTE_AUTHZ = `api:${CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG}`; -const ADVANCED_EXECUTE_AUTHZ = `api:${CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG}`; +const ADVANCED_EXECUTE_AUTHZ = `api:${CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG}`; function mockSecurity() { const security = securityMock.createSetup(); diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index 5174ccfbeeae8..151e142d104d7 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -14,11 +14,12 @@ import { CONNECTOR_TOKEN_SAVED_OBJECT_TYPE, } from './constants/saved_objects'; +export const CONNECTORS_ADVANCED_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-advanced-connectors'; +export const CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-basic-connectors'; + export const CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-edr-connectors'; export const CONNECTORS_EDR_EXECUTE_PRIVILEGE = `api:${CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG}`; -export const CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-basic-connectors'; - /** * The order of appearance in the feature privilege page * under the management section. @@ -40,7 +41,7 @@ export const ACTIONS_FEATURE = { privileges: { all: { app: [], - api: [CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG], + api: [], catalogue: [], management: { insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], @@ -57,7 +58,7 @@ export const ACTIONS_FEATURE = { }, read: { app: [], - api: [CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG], + api: [], catalogue: [], management: { insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], From 372012af60e7129d31d1d76edbeb6570e0c3d065 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 4 Dec 2024 09:00:58 -0800 Subject: [PATCH 13/15] Removing consumer --- .../server/application/rule/methods/update/update_rule.ts | 2 +- .../alerting/server/rules_client/lib/validate_actions.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts index 65e1c21702f3c..25759e8e06c70 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/update/update_rule.ts @@ -211,7 +211,7 @@ async function updateWithOCC( const actionsClient = await context.getActionsClient(); const validatedRuleTypeParams = validateRuleTypeParams(data.params, ruleType.validate.params); - await validateActions(context, ruleType, data, consumer, allowMissingConnectorSecrets); + await validateActions(context, ruleType, data, allowMissingConnectorSecrets); await validateAndAuthorizeSystemActions({ actionsClient, actionsAuthorization: context.actionsAuthorization, diff --git a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts index e9885e7ef730e..79c24bc842e5d 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts @@ -24,7 +24,6 @@ export async function validateActions( context: RulesClientContext, ruleType: UntypedNormalizedRuleType, data: ValidateActionsData, - consumer: string, allowMissingConnectorSecrets?: boolean ): Promise { const { actions, notifyWhen, throttle, systemActions = [] } = data; From 243cacc1f1db73b73a5a66fbb4ddbd8a02b34e12 Mon Sep 17 00:00:00 2001 From: Alexandra Doak Date: Wed, 4 Dec 2024 10:17:30 -0800 Subject: [PATCH 14/15] Adding back rbac --- x-pack/plugins/actions/server/feature.ts | 28 +++++++++++++++++++ .../connector_types/sentinelone/index.ts | 15 +++++++--- .../public/application/lib/capabilities.ts | 4 +-- .../edit_connector_flyout/header.tsx | 4 ++- .../edit_connector_flyout/index.tsx | 1 + .../components/actions_connectors_list.tsx | 7 +++-- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index 151e142d104d7..5809bfa6eff68 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -19,6 +19,7 @@ export const CONNECTORS_BASIC_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-basic export const CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG = 'actions:execute-edr-connectors'; export const CONNECTORS_EDR_EXECUTE_PRIVILEGE = `api:${CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG}`; +export const SUB_ACTIONS_EDR_EXECUTE_PRIVILEGE = `api:actions:execute-edr-sub_actions`; /** * The order of appearance in the feature privilege page @@ -71,4 +72,31 @@ export const ACTIONS_FEATURE = { ui: ['show', 'execute'], }, }, + subFeatures: [ + { + name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureName', { + defaultMessage: 'EDR Connectors', + }), + privilegeGroups: [ + { + groupType: 'independent', + privileges: [ + { + api: [CONNECTORS_EDR_EXECUTE_PRIVILEGE_API_TAG], + id: 'executeEdrConnectors', + name: i18n.translate('xpack.actions.featureRegistry.edrSubFeatureDetails', { + defaultMessage: 'Execute advanced EDR connectors', + }), + includeIn: 'all', + savedObject: { + all: [ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, CONNECTOR_TOKEN_SAVED_OBJECT_TYPE], + read: [ACTION_SAVED_OBJECT_TYPE], + }, + ui: ['executeEdr'], + }, + ], + }, + ], + }, + ], }; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts index 3ab5376df74cc..fce6915c1d980 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts @@ -11,7 +11,10 @@ import { } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { EdrForSecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; import { urlAllowListValidator, ActionExecutionSourceType } from '@kbn/actions-plugin/server'; -import { CONNECTORS_EDR_EXECUTE_PRIVILEGE } from '@kbn/actions-plugin/server/feature'; +import { + CONNECTORS_EDR_EXECUTE_PRIVILEGE, + SUB_ACTIONS_EDR__EXECUTE_PRIVILEGE, +} from '@kbn/actions-plugin/server/feature'; import { SENTINELONE_CONNECTOR_ID, SENTINELONE_TITLE } from '../../../common/sentinelone/constants'; import { SUB_ACTION } from '../../../common/sentinelone/constants'; @@ -40,9 +43,13 @@ export const getSentinelOneConnectorType = (): SubActionConnectorType< renderParameterTemplates, isEdrActionType: true, getKibanaPrivileges: (args) => { - return args?.source === ActionExecutionSourceType.HTTP_REQUEST && + const privileges = [CONNECTORS_EDR_EXECUTE_PRIVILEGE]; + if ( + args?.source === ActionExecutionSourceType.HTTP_REQUEST && args?.params?.subAction !== SUB_ACTION.GET_AGENTS - ? [CONNECTORS_EDR_EXECUTE_PRIVILEGE] - : []; + ) { + privileges.push(SUB_ACTIONS_EDR__EXECUTE_PRIVILEGE); + } + return privileges; }, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts index 1c31cb30aaaf9..1ea5774845dd1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/capabilities.ts @@ -18,8 +18,8 @@ type Capabilities = Record; export const hasShowActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.show; export const hasSaveActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.save; -export const hasExecuteActionsCapability = (capabilities: Capabilities) => - capabilities?.actions?.execute; +export const hasExecuteActionsCapability = (capabilities: Capabilities, isEdrAction?: boolean) => + isEdrAction ? capabilities?.actions?.executeEdr : capabilities?.actions?.execute; export const hasDeleteActionsCapability = (capabilities: Capabilities) => capabilities?.actions?.delete; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx index 9bce14109b605..508546e5529d9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/header.tsx @@ -29,6 +29,7 @@ import { hasExecuteActionsCapability } from '../../../lib/capabilities'; const FlyoutHeaderComponent: React.FC<{ isExperimental?: boolean; + isEdrActionType?: boolean; isPreconfigured: boolean; connectorName: string; connectorTypeDesc: string; @@ -38,6 +39,7 @@ const FlyoutHeaderComponent: React.FC<{ }> = ({ icon, isExperimental = false, + isEdrActionType = false, isPreconfigured, connectorName, connectorTypeDesc, @@ -49,7 +51,7 @@ const FlyoutHeaderComponent: React.FC<{ } = useKibana().services; const { euiTheme } = useEuiTheme(); - const canExecute = hasExecuteActionsCapability(capabilities); + const canExecute = hasExecuteActionsCapability(capabilities, isEdrActionType); const setConfigurationTab = useCallback(() => { setTab(EditConnectorTabs.Configuration); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index 8ae7e11fb2c0e..21ff098f81b93 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -321,6 +321,7 @@ const EditConnectorFlyoutComponent: React.FC = ({ selectedTab={selectedTab} icon={actionTypeModel?.iconClass} isExperimental={actionTypeModel?.isExperimental} + isEdrActionType={actionTypeModel?.isEdrActionType} /> {selectedTab === EditConnectorTabs.Configuration && renderConfigurationTab()} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 32942167a200a..ab551c23d54d7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -339,9 +339,12 @@ const ActionsConnectorsList = ({ Date: Thu, 5 Dec 2024 09:04:24 -0800 Subject: [PATCH 15/15] Fixing typo --- .../server/connector_types/sentinelone/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts index fce6915c1d980..4bffbb1c966d0 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/index.ts @@ -13,7 +13,7 @@ import { EdrForSecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; import { urlAllowListValidator, ActionExecutionSourceType } from '@kbn/actions-plugin/server'; import { CONNECTORS_EDR_EXECUTE_PRIVILEGE, - SUB_ACTIONS_EDR__EXECUTE_PRIVILEGE, + SUB_ACTIONS_EDR_EXECUTE_PRIVILEGE, } from '@kbn/actions-plugin/server/feature'; import { SENTINELONE_CONNECTOR_ID, SENTINELONE_TITLE } from '../../../common/sentinelone/constants'; import { SUB_ACTION } from '../../../common/sentinelone/constants'; @@ -48,7 +48,7 @@ export const getSentinelOneConnectorType = (): SubActionConnectorType< args?.source === ActionExecutionSourceType.HTTP_REQUEST && args?.params?.subAction !== SUB_ACTION.GET_AGENTS ) { - privileges.push(SUB_ACTIONS_EDR__EXECUTE_PRIVILEGE); + privileges.push(SUB_ACTIONS_EDR_EXECUTE_PRIVILEGE); } return privileges; },