Skip to content

Commit

Permalink
[8.x] [Epic] Knowledge Base - API integration tests (#8737) (#197290) (
Browse files Browse the repository at this point in the history
…#197525)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Epic] Knowledge Base - API integration tests (#8737)
(#197290)](#197290)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Ievgen
Sorokopud","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-23T19:58:09Z","message":"[Epic]
Knowledge Base - API integration tests (#8737) (#197290)\n\n##
Summary\r\n\r\nThis is a followup to the main Knowledge Base changes
where we've:\r\n1. Fixed the issue with access control to KB entries via
bulk actions\r\nAPIs\r\n2. Added the RBAC validation for the bulk
actions API\r\n3. Added integration tests to cover the bulk actions
API\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- Genai KB integration tests: [100
ESS +
100\r\nServerless](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7208)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"fd538614631c85c7cd3580e7d3270b9d38c57713","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:
SecuritySolution","backport:prev-minor","Feature:Security
Assistant","Team:Security Generative AI","v8.16.0"],"title":"[Epic]
Knowledge Base - API integration tests
(#8737)","number":197290,"url":"https://github.com/elastic/kibana/pull/197290","mergeCommit":{"message":"[Epic]
Knowledge Base - API integration tests (#8737) (#197290)\n\n##
Summary\r\n\r\nThis is a followup to the main Knowledge Base changes
where we've:\r\n1. Fixed the issue with access control to KB entries via
bulk actions\r\nAPIs\r\n2. Added the RBAC validation for the bulk
actions API\r\n3. Added integration tests to cover the bulk actions
API\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- Genai KB integration tests: [100
ESS +
100\r\nServerless](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7208)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"fd538614631c85c7cd3580e7d3270b9d38c57713"}},"sourceBranch":"main","suggestedTargetBranches":["8.16"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/197290","number":197290,"mergeCommit":{"message":"[Epic]
Knowledge Base - API integration tests (#8737) (#197290)\n\n##
Summary\r\n\r\nThis is a followup to the main Knowledge Base changes
where we've:\r\n1. Fixed the issue with access control to KB entries via
bulk actions\r\nAPIs\r\n2. Added the RBAC validation for the bulk
actions API\r\n3. Added integration tests to cover the bulk actions
API\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- Genai KB integration tests: [100
ESS +
100\r\nServerless](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7208)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"fd538614631c85c7cd3580e7d3270b9d38c57713"}},{"branch":"8.16","label":"v8.16.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Ievgen Sorokopud <[email protected]>
  • Loading branch information
kibanamachine and e40pud authored Oct 23, 2024
1 parent 23d02d7 commit 495de32
Show file tree
Hide file tree
Showing 8 changed files with 666 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,13 @@ export class DocumentsDataWriter implements DocumentsDataWriter {
{
bool: {
must_not: {
exists: {
field: 'users',
nested: {
path: 'users',
query: {
exists: {
field: 'users',
},
},
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@ import {
} from '../../../ai_assistant_data_clients/knowledge_base/types';
import { ElasticAssistantPluginRouter } from '../../../types';
import { buildResponse } from '../../utils';
import { transformESSearchToKnowledgeBaseEntry } from '../../../ai_assistant_data_clients/knowledge_base/transforms';
import {
transformESSearchToKnowledgeBaseEntry,
transformESToKnowledgeBase,
} from '../../../ai_assistant_data_clients/knowledge_base/transforms';
import {
getUpdateScript,
transformToCreateSchema,
transformToUpdateSchema,
} from '../../../ai_assistant_data_clients/knowledge_base/create_knowledge_base_entry';
import { getKBUserFilter } from './utils';

export interface BulkOperationError {
message: string;
Expand Down Expand Up @@ -179,8 +183,19 @@ export const bulkActionKnowledgeBaseEntriesRoute = (router: ElasticAssistantPlug
const spaceId = ctx.elasticAssistant.getSpaceId();
// Authenticated user null check completed in `performChecks()` above
const authenticatedUser = ctx.elasticAssistant.getCurrentUser() as AuthenticatedUser;
const userFilter = getKBUserFilter(authenticatedUser);
const manageGlobalKnowledgeBaseAIAssistant =
kbDataClient?.options.manageGlobalKnowledgeBaseAIAssistant;

if (body.create && body.create.length > 0) {
// RBAC validation
body.create.forEach((entry) => {
const isGlobal = entry.users != null && entry.users.length === 0;
if (isGlobal && !manageGlobalKnowledgeBaseAIAssistant) {
throw new Error(`User lacks privileges to create global knowledge base entries`);
}
});

const result = await kbDataClient?.findDocuments<EsKnowledgeBaseEntrySchema>({
perPage: 100,
page: 1,
Expand All @@ -199,6 +214,44 @@ export const bulkActionKnowledgeBaseEntriesRoute = (router: ElasticAssistantPlug
}
}

const validateDocumentsModification = async (
documentIds: string[],
operation: 'delete' | 'update'
) => {
if (!documentIds.length) {
return;
}
const documentsFilter = documentIds.map((id) => `_id:${id}`).join(' OR ');
const entries = await kbDataClient?.findDocuments<EsKnowledgeBaseEntrySchema>({
page: 1,
perPage: 100,
filter: `${documentsFilter} AND ${userFilter}`,
});
const availableEntries = entries
? transformESSearchToKnowledgeBaseEntry(entries.data)
: [];
availableEntries.forEach((entry) => {
// RBAC validation
const isGlobal = entry.users != null && entry.users.length === 0;
if (isGlobal && !manageGlobalKnowledgeBaseAIAssistant) {
throw new Error(
`User lacks privileges to ${operation} global knowledge base entries`
);
}
});
const availableIds = availableEntries.map((doc) => doc.id);
const nonAvailableIds = documentIds.filter((id) => !availableIds.includes(id));
if (nonAvailableIds.length > 0) {
throw new Error(`Could not find documents to ${operation}: ${nonAvailableIds}.`);
}
};

await validateDocumentsModification(body.delete?.ids ?? [], 'delete');
await validateDocumentsModification(
body.update?.map((entry) => entry.id) ?? [],
'update'
);

const writer = await kbDataClient?.getWriter();
const changedAt = new Date().toISOString();
const {
Expand All @@ -214,11 +267,11 @@ export const bulkActionKnowledgeBaseEntriesRoute = (router: ElasticAssistantPlug
spaceId,
user: authenticatedUser,
entry,
global: entry.users != null && entry.users.length === 0,
})
),
documentsToDelete: body.delete?.ids,
documentsToUpdate: body.update?.map((entry) =>
// TODO: KB-RBAC check, required when users != null as entry will either be created globally if empty
transformToUpdateSchema({
user: authenticatedUser,
updatedAt: changedAt,
Expand All @@ -241,9 +294,10 @@ export const bulkActionKnowledgeBaseEntriesRoute = (router: ElasticAssistantPlug

return buildBulkResponse(response, {
// @ts-ignore-next-line TS2322
updated: docsUpdated,
updated: transformESToKnowledgeBase(docsUpdated),
created: created?.data ? transformESSearchToKnowledgeBaseEntry(created?.data) : [],
deleted: docsDeleted ?? [],
skipped: [],
errors,
});
} catch (err) {
Expand Down
Loading

0 comments on commit 495de32

Please sign in to comment.