Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Observability AI Assistant Tests Deployment Agnostic #205194

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
cc983ea
Add ObservabilityAIAssistantApi Client deployment agnostic
arturoliduena Dec 27, 2024
f322689
Migrating existing conversations.spec.ts test to to deployment-agnost…
arturoliduena Dec 27, 2024
fe98f91
Add CODEOWNERS entry for deployment-agnostic AI Assistant API tests
arturoliduena Dec 27, 2024
6612952
remove duplicated conversations.spec.ts tests between stateful and se…
arturoliduena Dec 27, 2024
1dc1987
Migrating existing connectors.spec.ts test to deployment-agnostic test
arturoliduena Dec 27, 2024
fce7822
Migrating existing chat.spec.ts test to deployment-agnostic test
arturoliduena Jan 3, 2025
2d47596
Add unauthorized user role handling and migrate conversations tests t…
arturoliduena Jan 4, 2025
d0505ee
Add unauthorized user role handling and migrate connectors tests to d…
arturoliduena Jan 4, 2025
dd65895
Add security role checks for AI assistant chat API and remove legacy …
arturoliduena Jan 4, 2025
59e9148
Add complete.spec.ts to AI assistant API integration deployment diagn…
arturoliduena Jan 5, 2025
2db6c01
Migrating existing alerts.spec.ts test to deployment-agnostic test
arturoliduena Jan 5, 2025
c82e571
Add skipMKI tag to alerts function deployment-agnostic test
arturoliduena Jan 5, 2025
addf2d1
Migrating existing elasticsearch.spec.ts test to deployment-agnostic …
arturoliduena Jan 5, 2025
f4b3961
Add skipMKI tag to elasticsearch.spec.ts function deployment-agnostic…
arturoliduena Jan 5, 2025
d7e28b5
Migrating existing public_complete.spec.ts test to deployment-agnosti…
arturoliduena Jan 5, 2025
b80b0ee
Refactor ai_assistant tests to use viewer role instead of unauthorize…
arturoliduena Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ packages/kbn-monaco/src/esql @elastic/kibana-esql
/x-pack/test/observability_ai_assistant_functional @elastic/obs-ai-assistant
/x-pack/test_serverless/**/test_suites/observability/ai_assistant @elastic/obs-ai-assistant
/x-pack/test/functional/es_archives/observability/ai_assistant @elastic/obs-ai-assistant

/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant @elastic/obs-ai-assistant
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look related to your change but Github complains about errors in this file

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's valid on main which is odd

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out, @sorenlouv. I checked, and the file is now valid in this branch as well. It might have been a temporary issue or something resolved during recent changes(I did a rebase recently).

# Infra Obs
## This plugin mostly contains the codebase for the infra services, but also includes some code for the Logs UI app.
## To keep @elastic/obs-ux-logs-team as codeowner of the plugin manifest without requiring a review for all the other code changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@
import expect from '@kbn/expect';
import { MessageRole, type Message } from '@kbn/observability-ai-assistant-plugin/common';
import { PassThrough } from 'stream';
import { createLlmProxy, LlmProxy } from '../../common/create_llm_proxy';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import { createProxyActionConnector, deleteActionConnector } from '../../common/action_connectors';
import { ForbiddenApiError } from '../../common/config';

export default function ApiTest({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
import {
LlmProxy,
createLlmProxy,
} from '../../../../../../observability_ai_assistant_api_integration/common/create_llm_proxy';
import { SupertestWithRoleScope } from '../../../../services/role_scoped_supertest';
import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';

export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) {
const log = getService('log');
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');

const CHAT_API_URL = `/internal/observability_ai_assistant/chat`;
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi');

const messages: Message[] = [
{
Expand All @@ -37,37 +36,50 @@ export default function ApiTest({ getService }: FtrProviderContext) {
},
];

describe('/internal/observability_ai_assistant/chat', () => {
describe('/internal/observability_ai_assistant/chat', function () {
// TODO: https://github.com/elastic/kibana/issues/192751
this.tags(['skipMKI']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can be replace skipMKI with failsOnMKI if we want to be more descriptive that we aren't wanting to skip but that its failing so we have to skip.

let proxy: LlmProxy;

let connectorId: string;

before(async () => {
proxy = await createLlmProxy(log);
connectorId = await createProxyActionConnector({ supertest, log, port: proxy.getPort() });
connectorId = await observabilityAIAssistantAPIClient.createProxyActionConnector({
port: proxy.getPort(),
});
});

after(async () => {
proxy.close();
await deleteActionConnector({ supertest, connectorId, log });
await observabilityAIAssistantAPIClient.deleteActionConnector({
actionId: connectorId,
});
});

it("returns a 4xx if the connector doesn't exist", async () => {
await supertest
.post(CHAT_API_URL)
.set('kbn-xsrf', 'foo')
.send({
name: 'my_api_call',
messages,
connectorId: 'does not exist',
functions: [],
scopes: ['all'],
})
.expect(404);
const { status } = await observabilityAIAssistantAPIClient.editor({
endpoint: 'POST /internal/observability_ai_assistant/chat',
params: {
body: {
name: 'my_api_call',
messages,
connectorId: 'does not exist',
functions: [],
scopes: ['all'],
},
},
});
expect(status).to.be(404);
});

it('returns a streaming response from the server', async () => {
const NUM_RESPONSES = 5;
const roleScopedSupertest = getService('roleScopedSupertest');
const supertestEditorWithCookieCredentials: SupertestWithRoleScope =
await roleScopedSupertest.getSupertestWithRoleScope('editor', {
useCookieHeader: true,
withInternalHeaders: true,
});

await Promise.race([
new Promise((resolve, reject) => {
Expand All @@ -81,9 +93,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const receivedChunks: Array<Record<string, any>> = [];

const passThrough = new PassThrough();
supertest
.post(CHAT_API_URL)
.set('kbn-xsrf', 'foo')
supertestEditorWithCookieCredentials
.post('/internal/observability_ai_assistant/chat')
.on('error', reject)
.send({
name: 'my_api_call',
Expand Down Expand Up @@ -136,26 +147,21 @@ export default function ApiTest({ getService }: FtrProviderContext) {
}),
]);
});

describe('security roles and access privileges', () => {
it('should deny access for users without the ai_assistant privilege', async () => {
try {
await observabilityAIAssistantAPIClient.unauthorizedUser({
endpoint: `POST ${CHAT_API_URL}`,
params: {
body: {
name: 'my_api_call',
messages,
connectorId,
functions: [],
scopes: ['all'],
},
const { status } = await observabilityAIAssistantAPIClient.viewer({
endpoint: 'POST /internal/observability_ai_assistant/chat',
params: {
body: {
name: 'my_api_call',
messages,
connectorId,
functions: [],
scopes: ['all'],
},
});
throw new ForbiddenApiError('Expected unauthorizedUser() to throw a 403 Forbidden error');
} catch (e) {
expect(e.status).to.be(403);
}
},
});
expect(status).to.be(403);
});
});
});
Expand Down
Loading