kibana/x-pack/solutions/security/plugins/security_solution/server/config.mock.ts
Tiago Vila Verde a8a7574c66
[Entity Analytics][Privmon] CSV upload (#221798)
## Summary
 
This PR adds the ability to upload a CSV file with privileged users from
the Entity Analytics pages

## Changes

### Backend

- Added (or completed) the upload CSV route:
`/api/entity_analytics/monitoring/users/_csv`
- Added shared utilities for batching with Node streams
- Added bulk processing actions for the upload
  - Parsing users from CSV
  - Soft delete for omitted users 
  - Batch upsert via the bulk API
- Added a check for installing all required privmon resources

### Frontend

- File uploader components
- File validation logic
- Updated EA privmon page to account for the new flow
- Added managing users panels 
  - open upload flow (same as asset criticality)

## Screen recording


https://github.com/user-attachments/assets/7956f1cf-49e0-4430-8c23-7d6178a15342

## How to test

#### Prerequisite

Make sure you have a CSV file with usernames
Check
[here](https://gist.github.com/tiansivive/0be2f09e1bb380fdde6609a131e929ed)
for a little helper script

Create a few copies where some of the users are deleted, in order to
test soft delete

1. Start up kibana and ES
2. Navigate to Security > Entity Analytics > Privilege User Monitoring
3. Select the `File` option to add data
4. Add one of the CSV files to the open modal and upload
5. Repeat but now upload one of files with the omitted users 

Alternatively, testing only the backend only is possible by directly
hitting the API wit curl
```
curl -u elastic:changeme \
  -X POST "http://localhost:5601/api/entity_analytics/monitoring/users/_csv" \
  -H "kbn-xsrf: true" \
  -F "file=@test.csv;type=text/csv"
```

#### Verifying

Easiest way is to use the dev tools to `_search` the privmon users index
with:
```
GET .entity_analytics.monitoring.users-default/_search
```

Look for number of hits and/or use `query` to search for omitted users. 


## Remaining work

- [x] API integration tests
- [ ] Batching logic unit tests
- [ ] E2E tests?

---------

Co-authored-by: machadoum <pablo.nevesmachado@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
2025-06-18 15:23:03 +02:00

84 lines
2.6 KiB
TypeScript

/*
* 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 { DEFAULT_SIGNALS_INDEX, SIGNALS_INDEX_KEY } from '../common/constants';
import type { ExperimentalFeatures } from '../common/experimental_features';
import { parseExperimentalConfigValue } from '../common/experimental_features';
import { getDefaultConfigSettings } from '../common/config_settings';
import type { ConfigType } from './config';
import { duration } from 'moment';
export const createMockConfig = (): ConfigType => {
const enableExperimental: Array<keyof ExperimentalFeatures> = ['responseActionUploadEnabled'];
return {
[SIGNALS_INDEX_KEY]: DEFAULT_SIGNALS_INDEX,
maxRuleImportExportSize: 10000,
maxRuleImportPayloadBytes: 10485760,
maxTimelineImportExportSize: 10000,
maxTimelineImportPayloadBytes: 10485760,
enableExperimental,
packagerTaskInterval: '60s',
packagerTaskTimeout: '5m',
packagerTaskPackagePolicyUpdateBatchSize: 10,
completeExternalResponseActionsTaskInterval: '60s',
completeExternalResponseActionsTaskTimeout: '20m',
prebuiltRulesPackageVersion: '',
alertMergeStrategy: 'missingFields',
alertIgnoreFields: [],
maxUploadResponseActionFileBytes: 26214400,
settings: getDefaultConfigSettings(),
experimentalFeatures: parseExperimentalConfigValue(enableExperimental).features,
enabled: true,
enableUiSettingsValidations: false,
entityAnalytics: {
riskEngine: {
alertSampleSizePerShard: 10_000,
},
assetCriticality: {
csvUpload: {
errorRetries: 3,
maxBulkRequestBodySizeBytes: 10_485_760,
},
},
entityStore: {
frequency: duration('1m'),
syncDelay: duration('5m'),
developer: {
pipelineDebugMode: false,
},
},
monitoring: {
privileges: {
users: {
csvUpload: {
errorRetries: 3,
maxBulkRequestBodySizeBytes: 10_485_760,
},
},
},
},
},
};
};
const withExperimentalFeature = (
config: ConfigType,
feature: keyof ExperimentalFeatures
): ConfigType => {
const enableExperimental = config.enableExperimental.concat(feature);
return {
...config,
enableExperimental,
experimentalFeatures: parseExperimentalConfigValue(enableExperimental).features,
};
};
export const configMock = {
createDefault: createMockConfig,
withExperimentalFeature,
};