Skip to content

Commit

Permalink
check permissions before custom definition operations
Browse files Browse the repository at this point in the history
  • Loading branch information
klacabane committed Nov 8, 2024
1 parent 5df5069 commit 7e6ba5d
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 13 deletions.
20 changes: 12 additions & 8 deletions x-pack/plugins/entity_manager/server/lib/auth/privileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ import { ENTITY_INTERNAL_INDICES_PATTERN } from '../../../common/constants_entit
import { SO_ENTITY_DEFINITION_TYPE, SO_ENTITY_DISCOVERY_API_KEY_TYPE } from '../../saved_objects';
import { BUILT_IN_ALLOWED_INDICES } from '../entities/built_in/constants';

export const canManageEntityDefinition = async (client: ElasticsearchClient) => {
export const canManageEntityDefinition = async (
client: ElasticsearchClient,
sourceIndices: string[]
) => {
const { has_all_requested: hasAllRequested } = await client.security.hasPrivileges({
body: entityDefinitionRuntimePrivileges,
body: entityDefinitionRuntimePrivileges(sourceIndices),
});

return hasAllRequested;
};

const canDeleteEntityDefinition = async (client: ElasticsearchClient) => {
export const canDeleteEntityDefinition = async (client: ElasticsearchClient) => {
const { has_all_requested: hasAllRequested } = await client.security.hasPrivileges({
body: entityDefinitionDeletionPrivileges,
});
Expand All @@ -43,9 +46,10 @@ const canDeleteAPIKey = async (client: ElasticsearchClient) => {
};

export const canEnableEntityDiscovery = async (client: ElasticsearchClient) => {
return Promise.all([canManageAPIKey(client), canManageEntityDefinition(client)]).then((results) =>
results.every(Boolean)
);
return Promise.all([
canManageAPIKey(client),
canManageEntityDefinition(client, BUILT_IN_ALLOWED_INDICES),
]).then((results) => results.every(Boolean));
};

export const canDisableEntityDiscovery = async (client: ElasticsearchClient) => {
Expand All @@ -54,7 +58,7 @@ export const canDisableEntityDiscovery = async (client: ElasticsearchClient) =>
);
};

export const entityDefinitionRuntimePrivileges = {
export const entityDefinitionRuntimePrivileges = (sourceIndices: string[]) => ({
cluster: ['manage_transform', 'manage_ingest_pipelines', 'manage_index_templates'],
index: [
{
Expand All @@ -73,7 +77,7 @@ export const entityDefinitionRuntimePrivileges = {
resources: ['*'],
},
],
};
});

export const entityDefinitionDeletionPrivileges = {
cluster: ['manage_transform', 'manage_ingest_pipelines', 'manage_index_templates'],
Expand Down
17 changes: 16 additions & 1 deletion x-pack/plugins/entity_manager/server/routes/entities/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { EntityIdConflict } from '../../lib/entities/errors/entity_id_conflict_e
import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception';
import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error';
import { createEntityManagerServerRoute } from '../create_entity_manager_server_route';
import { canManageEntityDefinition } from '../../lib/auth';

/**
* @openapi
Expand Down Expand Up @@ -62,8 +63,22 @@ export const createEntityDefinitionRoute = createEntityManagerServerRoute({
query: createEntityDefinitionQuerySchema,
body: entityDefinitionSchema,
}),
handler: async ({ request, response, params, logger, getScopedClient }) => {
handler: async ({ context, request, response, params, logger, getScopedClient }) => {
try {
const currentUserClient = (await context.core).elasticsearch.client.asCurrentUser;
const isAuthorized = await canManageEntityDefinition(
currentUserClient,
params.body.indexPatterns
);
if (!isAuthorized) {
return response.forbidden({
body: {
message:
'Current Kibana user does not have the required permissions to create the entity definition',
},
});
}

const client = await getScopedClient({ request });
const definition = await client.createEntityDefinition({
definition: params.body,
Expand Down
14 changes: 13 additions & 1 deletion x-pack/plugins/entity_manager/server/routes/entities/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { EntityDefinitionNotFound } from '../../lib/entities/errors/entity_not_f
import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception';
import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error';
import { createEntityManagerServerRoute } from '../create_entity_manager_server_route';
import { canDeleteEntityDefinition } from '../../lib/auth/privileges';

/**
* @openapi
Expand Down Expand Up @@ -64,8 +65,19 @@ export const deleteEntityDefinitionRoute = createEntityManagerServerRoute({
path: deleteEntityDefinitionParamsSchema,
query: deleteEntityDefinitionQuerySchema,
}),
handler: async ({ request, response, params, logger, getScopedClient }) => {
handler: async ({ context, request, response, params, logger, getScopedClient }) => {
try {
const currentUserClient = (await context.core).elasticsearch.client.asCurrentUser;
const isAuthorized = await canDeleteEntityDefinition(currentUserClient);
if (!isAuthorized) {
return response.forbidden({
body: {
message:
'Current Kibana user does not have the required permissions to delete the entity definition',
},
});
}

const client = await getScopedClient({ request });
await client.deleteEntityDefinition({
id: params.path.id,
Expand Down
30 changes: 27 additions & 3 deletions x-pack/plugins/entity_manager/server/routes/entities/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { InvalidTransformError } from '../../lib/entities/errors/invalid_transfo
import { createEntityManagerServerRoute } from '../create_entity_manager_server_route';
import { EntityDefinitionNotFound } from '../../lib/entities/errors/entity_not_found';
import { EntityDefinitionUpdateConflict } from '../../lib/entities/errors/entity_definition_update_conflict';
import { findEntityDefinitionById } from '../../lib/entities/find_entity_definition';
import { canManageEntityDefinition } from '../../lib/auth';

/**
* @openapi
Expand Down Expand Up @@ -65,10 +67,32 @@ export const updateEntityDefinitionRoute = createEntityManagerServerRoute({
path: z.object({ id: z.string() }),
body: entityDefinitionUpdateSchema,
}),
handler: async ({ request, response, params, logger, getScopedClient }) => {
const entityClient = await getScopedClient({ request });

handler: async ({ context, request, response, params, logger, getScopedClient }) => {
try {
const core = await context.core;
const definition = await findEntityDefinitionById({
id: params.path.id,
esClient: core.elasticsearch.client.asCurrentUser,
soClient: core.savedObjects.client,
});
if (!definition) {
throw new EntityDefinitionNotFound(`Unable to find entity definition [${params.path.id}]`);
}

const isAuthorized = await canManageEntityDefinition(
core.elasticsearch.client.asCurrentUser,
params.body.indexPatterns ?? definition.indexPatterns
);
if (!isAuthorized) {
return response.forbidden({
body: {
message:
'Current Kibana user does not have the required permissions to update the entity definition',
},
});
}

const entityClient = await getScopedClient({ request });
const updatedDefinition = await entityClient.updateEntityDefinition({
id: params.path.id,
definitionUpdate: params.body,
Expand Down

0 comments on commit 7e6ba5d

Please sign in to comment.