[Security Solution] API tests for AI4DSOC effort (#215318)

## Summary  
This PR establishes the foundation for executing API tests in the new
`search_ai_lake` tier, following the existing API integration test
structure and guidelines.

## Adding a New Test  
To add a new test, follow these guidelines:  

- Inside the `AI4DSOC` folder, create subfolders representing different
AI4DSOC functionalities.
- Each subfolder should be owned by an area team or the developers
actively working on it.
- The functionality folder must include a `search_ai_lake_tier`
subfolder.
- The `search_ai_lake_tier` subfolder should contain a `configs`
directory with a `serverless.config.ts` file that imports
`createTestConfig` from `config.base.ai4dsoc`.
- Add the test inside the `search_ai_lake_tier` subfolder.  
- Ensure the test has the `@serverless` label and uses
`supertestWithoutAuth` instead of `supertest`, as `supertest` provides
basic authentication, whereas serverless environments require API key
authentication. See the `dummy_test.ts` for reference.
- The `search_ai_lake_tier` folder should have an `index.ts` file
referencing the tests to be executed, as demonstrated in this PR.
- Update the
`x-pack/test/security_solution_api_integration/package.json` file with
the necessary scripts to enable test execution locally.
- When adding a new `serverless.config.ts` file, ensure it is included
in `.buildkite/ftr_security_serverless_configs.yml`. Otherwise, the new
test(s) will not be executed as part of the PR process.

## Running Tests Locally  
Execute the tests using the following Yarn scripts from
`x-pack/test/security_solution_api_integration`:

1. Start the server with the required configuration:  
   ```sh
   yarn ai4dsoc_cases:server:serverless
   ```
2. Run the tests using the started server:
  ```sh
  yarn ai4dsoc_cases🏃serverless
  ```
  
## Key Considerations
- `Supertest` should not be used, as it provides basic authentication.
Instead, use supertestWithoutAuth for API key authentication.
- All tests must include the `@serverless` label.
- MKI is not yet supported for test execution.
- Temporary Ownership: The Security Engineering Productivity team will
initially own the AI4DSOC testing folder to ensure proper structure and
best practices. Once teams are familiar with the workflow, this
ownership will be removed.
   
## Security Engineering Productivity Code Ownership Responsibilities
The Security Engineering Productivity team should ensure:

- All tests are placed inside a functionality-specific subfolder.
- Each functionality subfolder has designated code owners.
- Tests include the `@serverless` label.
- `Supertest` is not used.
- The correct configuration is applied.
- Scripts are added to enable local execution.
- New configurations are added to
`.buildkite/ftr_security_serverless_configs.yml`.

## Follow-Up tasks
- Remove the existing dummy test.
- Integrate tests into the periodic pipeline.
- Add tests to the Kibana QA quality gate.
This commit is contained in:
Gloria Hornero 2025-03-20 20:11:04 +01:00 committed by GitHub
parent b39b8c4591
commit 91cf7b4266
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 147 additions and 0 deletions

View file

@ -3,6 +3,7 @@ disabled:
- x-pack/test/security_solution_api_integration/config/serverless/config.base.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.essentials.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.edr_workflows.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.ai4dsoc.ts
- x-pack/test/defend_workflows_cypress/serverless_config.base.ts
- x-pack/test/osquery_cypress/serverless_config.base.ts
@ -131,6 +132,7 @@ enabled:
- x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/configs/serverless.config.ts
- x-pack/test/security_solution_endpoint/configs/serverless.endpoint.config.ts
- x-pack/test/security_solution_endpoint/configs/serverless.integrations.config.ts
- x-pack/test/security_solution_api_integration/test_suites/ai4dsoc/cases/search_ai_lake_tier/configs/serverless.config.ts
# serverless config files that run deployment-agnostic tests
- x-pack/test/api_integration/deployment_agnostic/configs/serverless/security.serverless.config.ts
- x-pack/test/spaces_api_integration/deployment_agnostic/security_and_spaces/serverless.config.ts

1
.github/CODEOWNERS vendored
View file

@ -2229,6 +2229,7 @@ x-pack/test/api_integration/apis/management/index_management/inference_endpoints
# AI4DSOC in Security Solution
/x-pack/test/security_solution_cypress/cypress/e2e/ai4dsoc @elastic/security-engineering-productivity
/x-pack/test/security_solution_api_integration/test_suites/ai4dsoc @elastic/security-engineering-productivity
# Security Solution cross teams ownership
/x-pack/test/security_solution_cypress/cypress/fixtures @elastic/security-detections-response @elastic/security-threat-hunting

View file

@ -0,0 +1,53 @@
/*
* 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 { ScoutTestRunConfigCategory } from '@kbn/scout-info';
import { FtrConfigProviderContext } from '@kbn/test';
export interface CreateTestConfigOptions {
testFiles: string[];
junit: { reportName: string };
kbnTestServerArgs?: string[];
kbnTestServerEnv?: Record<string, string>;
}
import { services } from './services';
export function createTestConfig(options: CreateTestConfigOptions) {
return async ({ readConfigFile }: FtrConfigProviderContext) => {
const svlSharedConfig = await readConfigFile(
require.resolve('@kbn/test-suites-serverless/shared/config.base')
);
return {
...svlSharedConfig.getAll(),
testConfigCategory: ScoutTestRunConfigCategory.API_TEST,
services: {
...services,
},
kbnTestServer: {
...svlSharedConfig.get('kbnTestServer'),
serverArgs: [
...svlSharedConfig.get('kbnTestServer.serverArgs'),
'--serverless=security',
`--xpack.securitySolutionServerless.productTypes=${JSON.stringify([
{ product_line: 'ai_soc', product_tier: 'search_ai_lake' },
])}`,
...(options.kbnTestServerArgs || []),
],
env: {
...svlSharedConfig.get('kbnTestServer.env'),
...options.kbnTestServerEnv,
},
},
testFiles: options.testFiles,
junit: options.junit,
mochaOpts: {
...svlSharedConfig.get('mochaOpts'),
grep: '/^(?!.*@skipInServerless).*@serverless.*/',
},
};
};
}

View file

@ -61,6 +61,12 @@
"initialize-server:siem_migrations:trial_complete": "node ./scripts/index.js server siem_migrations trial_license_complete_tier",
"run-tests:siem_migrations:trial_complete": "node ./scripts/index.js runner siem_migrations trial_license_complete_tier",
"initialize-server:ai4dsoc": "node ./scripts/index.js server ai4dsoc search_ai_lake_tier",
"run-tests:ai4dsoc": "node ./scripts/index.js runner ai4dsoc search_ai_lake_tier",
"ai4dsoc_cases:server:serverless": "npm run initialize-server:ai4dsoc cases serverless",
"ai4dsoc_cases:runner:serverless": "npm run run-tests:ai4dsoc cases serverless serverlessEnv",
"genai_kb_entries:server:serverless": "npm run initialize-server:genai:trial_complete knowledge_base/entries serverless",
"genai_kb_entries:runner:serverless": "npm run run-tests:genai:trial_complete knowledge_base/entries serverless serverlessEnv",
"genai_kb_entries:qa:serverless": "npm run run-tests:genai:trial_complete knowledge_base/entries serverless qaPeriodicEnv",

View file

@ -0,0 +1,15 @@
/*
* 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 { createTestConfig } from '../../../../../config/serverless/config.base.ai4dsoc';
export default createTestConfig({
testFiles: [require.resolve('..')],
junit: {
reportName: 'AI4DSOC - Cases',
},
});

View file

@ -0,0 +1,56 @@
/*
* 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 { RoleCredentials, InternalRequestHeader } from '@kbn/ftr-common-functional-services';
import { DeploymentAgnosticFtrProviderContext } from '../../../../../api_integration/deployment_agnostic/ftr_provider_context';
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
const samlAuth = getService('samlAuth');
const supertestWithoutAuth = getService('supertestWithoutAuth');
let roleAuthc: RoleCredentials;
let internalHeaders: InternalRequestHeader;
describe('@serverless Dummy test', () => {
before(async () => {
roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('platform_engineer');
internalHeaders = samlAuth.getInternalRequestHeader();
});
after(async () => {
await samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc);
});
it('returns autocomplete definitions', async () => {
const body = {
tags: ['tag-1'],
owner: 'securitySolution',
title: 'Case title 1',
settings: {
syncAlerts: true,
},
connector: {
id: '131d4448-abe0-4789-939d-8ef60680b498',
name: 'My connector',
type: '.jira',
fields: {
parent: null,
priority: 'High',
issueType: '10006',
},
},
description: 'A case description.',
};
await supertestWithoutAuth
.post('/api/cases')
.set(roleAuthc.apiKeyHeader)
.set(internalHeaders)
.set('kbn-xsrf', 'true')
.send(body)
.expect(200);
});
});
}

View file

@ -0,0 +1,14 @@
/*
* 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 { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('AI4DSOC - Cases', function () {
loadTestFile(require.resolve('./dummy_test.ts'));
});
}