Skip to content

Commit

Permalink
[7.x] [RAC] Remove rbac on security solution side (#110472) (#110765)
Browse files Browse the repository at this point in the history
* [RAC] Remove rbac on security solution side (#110472)

* wip to remove rbac

* Revert "[Cases] Include rule registry client for updating alert statuses (#108588)"

This reverts commit 1fd7038.

This leaves the rule registry mock changes

* remove rbac on Trend/Count alert

* update detection api for status

* remove @kbn-alerts packages

* fix leftover

* Switching cases to leverage update by query for alert status

* Adding missed files

* fix bad logic

* updating tests for use_alerts_privileges

* remove index alias/fields

* fix types

* fix plugin to get the right index names

* left over of alis on template

* forget to use current user for create/read route index

* updated alerts page to not show table when no privileges and updates to tests

* fix bug when switching between o11y and security solution

* updates tests and move to use privileges page when user tries to access alerts without proper access

* updating jest tests

* pairing with yara

* bring back kbn-alerts after discussion with the team

* fix types

* fix index field for o11y

* fix bug with updating index priv state

* fix i18n issue and update api docs

* fix refresh on alerts

* fix render view on alerts

* updating tests and checking for null in alerts page to not show no privileges page before load

* fix details rules

Co-authored-by: Jonathan Buttner <jonathan.buttner@elastic.co>
Co-authored-by: Yara Tercero <yara.tercero@elastic.co>
# Conflicts:
#	x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts

* skip test

Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com>
  • Loading branch information
semd and XavierM committed Sep 1, 2021
1 parent 14a1103 commit 9e6a282
Show file tree
Hide file tree
Showing 77 changed files with 1,071 additions and 889 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ readonly links: {
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
Expand Down

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/core/public/doc_links/doc_links_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export class DocLinksService {
siem: {
guide: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`,
gettingStarted: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`,
privileges: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/sec-requirements.html`,
ml: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/machine-learning.html`,
ruleChangeLog: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/prebuilt-rules-changelog.html`,
detectionsReq: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/detections-permissions-section.html`,
Expand Down Expand Up @@ -571,6 +572,7 @@ export interface DocLinksStart {
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
Expand Down
1 change: 1 addition & 0 deletions src/core/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ export interface DocLinksStart {
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/cases/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"id":"cases",
"kibanaVersion":"kibana",
"optionalPlugins":[
"ruleRegistry",
"security",
"spaces"
],
Expand Down
14 changes: 11 additions & 3 deletions x-pack/plugins/cases/server/client/alerts/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ export const get = async (
{ alertsInfo }: AlertGet,
clientArgs: CasesClientArgs
): Promise<CasesClientGetAlertsResponse> => {
const { alertsService, logger } = clientArgs;
const { alertsService, scopedClusterClient, logger } = clientArgs;
if (alertsInfo.length === 0) {
return [];
}

const alerts = await alertsService.getAlerts({ alertsInfo, logger });
return alerts ?? [];
const alerts = await alertsService.getAlerts({ alertsInfo, scopedClusterClient, logger });
if (!alerts) {
return [];
}

return alerts.docs.map((alert) => ({
id: alert._id,
index: alert._index,
...alert._source,
}));
};
12 changes: 11 additions & 1 deletion x-pack/plugins/cases/server/client/alerts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@

import { CaseStatuses } from '../../../common/api';
import { AlertInfo } from '../../common';
import { Alert } from '../../services/alerts/types';

interface Alert {
id: string;
index: string;
destination?: {
ip: string;
};
source?: {
ip: string;
};
}

export type CasesClientGetAlertsResponse = Alert[];

Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/cases/server/client/alerts/update_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export const updateStatus = async (
{ alerts }: UpdateAlertsStatusArgs,
clientArgs: CasesClientArgs
): Promise<void> => {
const { alertsService, logger } = clientArgs;
await alertsService.updateAlertsStatus({ alerts, logger });
const { alertsService, scopedClusterClient, logger } = clientArgs;
await alertsService.updateAlertsStatus({ alerts, scopedClusterClient, logger });
};
34 changes: 31 additions & 3 deletions x-pack/plugins/cases/server/client/attachments/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ import {
} from '../../services/user_actions/helpers';

import { AttachmentService, CasesService, CaseUserActionService } from '../../services';
import { createCaseError, CommentableCase, isCommentRequestTypeGenAlert } from '../../common';
import {
createCaseError,
CommentableCase,
createAlertUpdateRequest,
isCommentRequestTypeGenAlert,
} from '../../common';
import { CasesClientArgs, CasesClientInternal } from '..';

import { decodeCommentRequest } from '../utils';
Expand Down Expand Up @@ -190,9 +195,22 @@ const addGeneratedAlerts = async (
user: userDetails,
commentReq: query,
id: savedObjectID,
casesClientInternal,
});

if (
(newComment.attributes.type === CommentType.alert ||
newComment.attributes.type === CommentType.generatedAlert) &&
caseInfo.attributes.settings.syncAlerts
) {
const alertsToUpdate = createAlertUpdateRequest({
comment: query,
status: subCase.attributes.status,
});
await casesClientInternal.alerts.updateStatus({
alerts: alertsToUpdate,
});
}

await userActionService.bulkCreate({
unsecuredSavedObjectsClient,
actions: [
Expand Down Expand Up @@ -368,9 +386,19 @@ export const addComment = async (
user: userInfo,
commentReq: query,
id: savedObjectID,
casesClientInternal,
});

if (newComment.attributes.type === CommentType.alert && updatedCase.settings.syncAlerts) {
const alertsToUpdate = createAlertUpdateRequest({
comment: query,
status: updatedCase.status,
});

await casesClientInternal.alerts.updateStatus({
alerts: alertsToUpdate,
});
}

await userActionService.bulkCreate({
unsecuredSavedObjectsClient,
actions: [
Expand Down
65 changes: 21 additions & 44 deletions x-pack/plugins/cases/server/client/cases/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import Boom from '@hapi/boom';
import { SavedObjectsFindResponse, SavedObject, Logger } from 'kibana/server';
import { SavedObjectsFindResponse, SavedObject } from 'kibana/server';

import {
ActionConnector,
Expand All @@ -22,16 +22,26 @@ import {
import { buildCaseUserActionItem } from '../../services/user_actions/helpers';

import { createIncident, getCommentContextFromAttributes } from './utils';
import {
AlertInfo,
createCaseError,
flattenCaseSavedObject,
getAlertInfoFromComments,
} from '../../common';
import { createCaseError, flattenCaseSavedObject, getAlertInfoFromComments } from '../../common';
import { CasesClient, CasesClientArgs, CasesClientInternal } from '..';
import { Operations } from '../../authorization';
import { casesConnectors } from '../../connectors';
import { CasesClientGetAlertsResponse } from '../alerts/types';

/**
* Returns true if the case should be closed based on the configuration settings and whether the case
* is a collection. Collections are not closable because we aren't allowing their status to be changed.
* In the future we could allow push to close all the sub cases of a collection but that's not currently supported.
*/
function shouldCloseByPush(
configureSettings: SavedObjectsFindResponse<CasesConfigureAttributes>,
caseInfo: SavedObject<CaseAttributes>
): boolean {
return (
configureSettings.total > 0 &&
configureSettings.saved_objects[0].attributes.closure_type === 'close-by-pushing' &&
caseInfo.attributes.type !== CaseType.collection
);
}

/**
* Parameters for pushing a case to an external system
Expand Down Expand Up @@ -96,7 +106,9 @@ export const push = async (

const alertsInfo = getAlertInfoFromComments(theCase?.comments);

const alerts = await getAlertsCatchErrors({ casesClientInternal, alertsInfo, logger });
const alerts = await casesClientInternal.alerts.get({
alertsInfo,
});

const getMappingsResponse = await casesClientInternal.configuration.getMappings({
connector: theCase.connector,
Expand Down Expand Up @@ -266,38 +278,3 @@ export const push = async (
throw createCaseError({ message: `Failed to push case: ${error}`, error, logger });
}
};

async function getAlertsCatchErrors({
casesClientInternal,
alertsInfo,
logger,
}: {
casesClientInternal: CasesClientInternal;
alertsInfo: AlertInfo[];
logger: Logger;
}): Promise<CasesClientGetAlertsResponse> {
try {
return await casesClientInternal.alerts.get({
alertsInfo,
});
} catch (error) {
logger.error(`Failed to retrieve alerts during push: ${error}`);
return [];
}
}

/**
* Returns true if the case should be closed based on the configuration settings and whether the case
* is a collection. Collections are not closable because we aren't allowing their status to be changed.
* In the future we could allow push to close all the sub cases of a collection but that's not currently supported.
*/
function shouldCloseByPush(
configureSettings: SavedObjectsFindResponse<CasesConfigureAttributes>,
caseInfo: SavedObject<CaseAttributes>
): boolean {
return (
configureSettings.total > 0 &&
configureSettings.saved_objects[0].attributes.closure_type === 'close-by-pushing' &&
caseInfo.attributes.type !== CaseType.collection
);
}
27 changes: 10 additions & 17 deletions x-pack/plugins/cases/server/client/cases/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';

import {
Logger,
SavedObject,
SavedObjectsClientContract,
SavedObjectsFindResponse,
Expand Down Expand Up @@ -308,14 +307,12 @@ async function updateAlerts({
caseService,
unsecuredSavedObjectsClient,
casesClientInternal,
logger,
}: {
casesWithSyncSettingChangedToOn: UpdateRequestWithOriginalCase[];
casesWithStatusChangedAndSynced: UpdateRequestWithOriginalCase[];
caseService: CasesService;
unsecuredSavedObjectsClient: SavedObjectsClientContract;
casesClientInternal: CasesClientInternal;
logger: Logger;
}) {
/**
* It's possible that a case ID can appear multiple times in each array. I'm intentionally placing the status changes
Expand Down Expand Up @@ -364,9 +361,7 @@ async function updateAlerts({
[]
);

await casesClientInternal.alerts.updateStatus({
alerts: alertsToUpdate,
});
await casesClientInternal.alerts.updateStatus({ alerts: alertsToUpdate });
}

function partitionPatchRequest(
Expand Down Expand Up @@ -567,6 +562,15 @@ export const update = async (
);
});

// Update the alert's status to match any case status or sync settings changes
await updateAlerts({
casesWithStatusChangedAndSynced,
casesWithSyncSettingChangedToOn,
caseService,
unsecuredSavedObjectsClient,
casesClientInternal,
});

const returnUpdatedCase = myCases.saved_objects
.filter((myCase) =>
updatedCases.saved_objects.some((updatedCase) => updatedCase.id === myCase.id)
Expand Down Expand Up @@ -594,17 +598,6 @@ export const update = async (
}),
});

// Update the alert's status to match any case status or sync settings changes
// Attempt to do this after creating/changing the other entities just in case it fails
await updateAlerts({
casesWithStatusChangedAndSynced,
casesWithSyncSettingChangedToOn,
caseService,
unsecuredSavedObjectsClient,
casesClientInternal,
logger,
});

return CasesResponseRt.encode(returnUpdatedCase);
} catch (error) {
const idVersions = cases.cases.map((caseInfo) => ({
Expand Down
19 changes: 11 additions & 8 deletions x-pack/plugins/cases/server/client/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
* 2.0.
*/

import { KibanaRequest, SavedObjectsServiceStart, Logger } from 'kibana/server';
import {
KibanaRequest,
SavedObjectsServiceStart,
Logger,
ElasticsearchClient,
} from 'kibana/server';
import { SecurityPluginSetup, SecurityPluginStart } from '../../../security/server';
import { SAVED_OBJECT_TYPES } from '../../common';
import { Authorization } from '../authorization/authorization';
Expand All @@ -20,8 +25,8 @@ import {
} from '../services';
import { PluginStartContract as FeaturesPluginStart } from '../../../features/server';
import { PluginStartContract as ActionsPluginStart } from '../../../actions/server';
import { RuleRegistryPluginStartContract } from '../../../rule_registry/server';
import { LensServerPluginSetup } from '../../../lens/server';

import { AuthorizationAuditLogger } from '../authorization';
import { CasesClient, createCasesClient } from '.';

Expand All @@ -31,7 +36,6 @@ interface CasesClientFactoryArgs {
getSpace: GetSpaceFn;
featuresPluginStart: FeaturesPluginStart;
actionsPluginStart: ActionsPluginStart;
ruleRegistryPluginStart?: RuleRegistryPluginStartContract;
lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory'];
}

Expand Down Expand Up @@ -65,10 +69,12 @@ export class CasesClientFactory {
*/
public async create({
request,
scopedClusterClient,
savedObjectsService,
}: {
request: KibanaRequest;
savedObjectsService: SavedObjectsServiceStart;
scopedClusterClient: ElasticsearchClient;
}): Promise<CasesClient> {
if (!this.isInitialized || !this.options) {
throw new Error('CasesClientFactory must be initialized before calling create');
Expand All @@ -88,12 +94,9 @@ export class CasesClientFactory {
const caseService = new CasesService(this.logger, this.options?.securityPluginStart?.authc);
const userInfo = caseService.getUser({ request });

const alertsClient = await this.options.ruleRegistryPluginStart?.getRacClientWithRequest(
request
);

return createCasesClient({
alertsService: new AlertService(alertsClient),
alertsService: new AlertService(),
scopedClusterClient,
unsecuredSavedObjectsClient: savedObjectsService.getScopedClient(request, {
includedHiddenTypes: SAVED_OBJECT_TYPES,
// this tells the security plugin to not perform SO authorization and audit logging since we are handling
Expand Down
Loading

0 comments on commit 9e6a282

Please sign in to comment.