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

Add frontend http client #7000

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
81616ca
feat(http): create http frontend client
Desvelao Sep 19, 2024
9189e8e
fix: add VSCode settings file
Desvelao Sep 19, 2024
af7e812
chore: remove comment
Desvelao Sep 19, 2024
3fe48aa
feat: add suggestions of code review
Desvelao Sep 27, 2024
7b4ed5b
feat(core): add TableData and ServerTable components to core plugin
Desvelao Oct 2, 2024
54d3fc0
test(core): fix ExportTableCsv test
Desvelao Oct 2, 2024
2634eeb
chore(prettier): fix some code syntax
Desvelao Oct 2, 2024
1bde358
chore(prettier): fix some code syntax
Desvelao Oct 2, 2024
57f213c
chore: remove console.log
Desvelao Oct 2, 2024
aad9930
feat(core): enhance typing
Desvelao Oct 2, 2024
3121f61
Merge branch 'master' of https://github.com/wazuh/wazuh-kibana-app in…
Desvelao Nov 27, 2024
5c965f0
fix(http): move type definitions
Desvelao Nov 27, 2024
bfff8dd
fix: tests
Desvelao Nov 27, 2024
ff38af0
fix: move types
Desvelao Nov 28, 2024
cbd5584
chore(changelog): add entry)
Desvelao Nov 28, 2024
bbce7b1
Merge branch 'master' of https://github.com/wazuh/wazuh-kibana-app in…
Desvelao Dec 3, 2024
6dedffc
fix(lint): code lint
Desvelao Dec 3, 2024
85c331c
fix(prettier): code prettier
Desvelao Dec 3, 2024
2e8cfcc
fix(lint): code lint
Desvelao Dec 3, 2024
f61763f
fix(lint): code lint
Desvelao Dec 4, 2024
38bede6
Update plugins/wazuh-core/public/services/http/server-client.ts
Desvelao Dec 5, 2024
4e656ce
Merge branch 'master' of https://github.com/wazuh/wazuh-kibana-app in…
Desvelao Dec 5, 2024
f433f64
fix(http): review suggestions
Desvelao Dec 5, 2024
eb3516b
fix(http): review suggestions
Desvelao Dec 5, 2024
4fcad8f
fix(http): fix options paramenter in http client
Desvelao Dec 5, 2024
2dcdc10
fix(lint): simplify arrow-body-style configuration in ESLint settings
guidomodarelli Dec 5, 2024
a907cd8
fix(types): enhance SearchBarQueryLanguage and refine query language …
guidomodarelli Dec 5, 2024
b4819d2
fix(lint): update ESLint rules for unicorn and TypeScript to improve …
guidomodarelli Dec 5, 2024
8d99e41
fix(lint): refine ESLint rules and clean up code with consistent erro…
guidomodarelli Dec 5, 2024
0f8289e
fix(lint): add rule for optional chaining and update WazuhApiCtrl for…
guidomodarelli Dec 6, 2024
9525a4b
fix(lint): simplify state update with optional chaining and improve c…
guidomodarelli Dec 6, 2024
824b184
fix(lint): optimize settings update and clean up settings grouping lo…
guidomodarelli Dec 6, 2024
642d749
fix(lint): enhance rule for optional chaining to include empty Object…
guidomodarelli Dec 6, 2024
e089526
fix(lint): simplify array mapping in AQL tests for improved readabili…
guidomodarelli Dec 6, 2024
f489338
fix(lint): refactor object mapping in AQL component for improved read…
guidomodarelli Dec 6, 2024
65c9800
fix(lint): streamline object mapping in WQL for enhanced readability …
guidomodarelli Dec 6, 2024
f5706d8
fix(lint): simplify object mapping in TableData for improved readabil…
guidomodarelli Dec 6, 2024
ad97a40
fix(lint): refactor object mapping in ExportTableCsv for improved rea…
guidomodarelli Dec 6, 2024
13e44e1
fix(lint): refactor error handling in GenericRequest for improved rea…
guidomodarelli Dec 6, 2024
51cbf6f
fix(lint): streamline error message extraction in WzRequest for impro…
guidomodarelli Dec 6, 2024
02e31a6
fix(lint): add rule for optional chaining with empty array expression…
guidomodarelli Dec 6, 2024
8f0ac56
fix(lint): refactor token extraction using optional chaining for impr…
guidomodarelli Dec 6, 2024
b670544
fix(enum): remove redundant enum definition for plugin settings, impr…
guidomodarelli Dec 6, 2024
8deb71f
fix(lint): add rule for empty functions in test files to enhance code…
guidomodarelli Dec 6, 2024
f33d351
fix(refactor): optimize settings categorization logic for clarity and…
guidomodarelli Dec 6, 2024
38c2bb6
fix(lint): remove unused variable warnings and improve code readabili…
guidomodarelli Dec 6, 2024
86efe85
fix(lint): eliminate unnecessary eslint-disable comments and enhance …
guidomodarelli Dec 6, 2024
04bcf98
fix(refactor): enhance search bar query language structure and type s…
guidomodarelli Dec 6, 2024
d1e9e59
fix(lint): turn off 'default-param-last' rule and clean up related es…
guidomodarelli Dec 6, 2024
e99506e
fix(lint): remove unused variables and clean up eslint-disable commen…
guidomodarelli Dec 6, 2024
5211788
fix(lint): update enum formatting rules in eslint config for improved…
guidomodarelli Dec 6, 2024
3c0cd7d
fix(aql): refactor token types to use enums and constants for improve…
guidomodarelli Dec 6, 2024
1b4dc2b
fix(lint): expand ESLint variable rule to include boolean, number, an…
guidomodarelli Dec 6, 2024
51b5842
fix(types): update UseStateStorageHook to default type 'any' for impr…
guidomodarelli Dec 6, 2024
7c5baf0
fix(lint): add camelCase and PascalCase formats for object literal me…
guidomodarelli Dec 6, 2024
3a156f6
fix(lint): include camelCase and PascalCase formats for variable name…
guidomodarelli Dec 6, 2024
db7cde7
fix(lint): update unused variable handling in table-data component to…
guidomodarelli Dec 6, 2024
b831512
fix(lint): enhance withServices HOC to set displayName for better deb…
guidomodarelli Dec 6, 2024
19f57c4
fix(lint): remove unused eslint disables and update callback paramete…
guidomodarelli Dec 6, 2024
4d2fc70
fix(lint): remove unnecessary eslint-disable comment in server-table-…
guidomodarelli Dec 6, 2024
d34108d
fix(lint): clean up request-interceptor by removing unused eslint-dis…
guidomodarelli Dec 6, 2024
cd48318
fix(lint): remove unnecessary eslint-disable comment from configurati…
guidomodarelli Dec 6, 2024
a4c5a12
fix(lint): remove unnecessary eslint-disable comments from configurat…
guidomodarelli Dec 6, 2024
4a9e48c
fix(lint): remove unused eslint-disable comment from search-bar compo…
guidomodarelli Dec 6, 2024
16ceef7
fix(lint): remove unused eslint-disable comment from wql.test.tsx to …
guidomodarelli Dec 6, 2024
846200e
fix(code): replace WQL.id with WQL_ID in query language file for bett…
guidomodarelli Dec 6, 2024
ca83f01
fix(lint): remove unused eslint-disable comment from server-client.ts…
guidomodarelli Dec 6, 2024
649a2e7
fix(lint): eliminate unused eslint-disable comments in wql.tsx to enh…
guidomodarelli Dec 6, 2024
1df9aa7
fix(lint): remove unnecessary eslint-disable comment in wql.tsx to im…
guidomodarelli Dec 6, 2024
8159bd6
fix(types): replace hardcoded id with WQL_ID in ISearchBarModeWQL int…
guidomodarelli Dec 6, 2024
1c30b77
fix(lint): refactor conditional logic in wql.tsx to improve code clar…
guidomodarelli Dec 6, 2024
a93ff85
fix(api): use WAZUH_ERROR_DAEMONS_NOT_READY constant for error messag…
guidomodarelli Dec 6, 2024
bd24178
fix(api): update WazuhApiCtrl to use WAZUH_ERROR_CODES for consistent…
guidomodarelli Dec 6, 2024
d1c7581
fix(lint): update eslint config to enforce UPPER_CASE for enum and ad…
guidomodarelli Dec 6, 2024
e8fb587
fix(settings-validator): refactor class to object, update methods for…
guidomodarelli Dec 6, 2024
675ee00
fix(lint): enhance eslint config to allow UPPER_CASE, camelCase, and …
guidomodarelli Dec 6, 2024
3f3f9e6
fix(constants): update import path and refactor configuration constan…
guidomodarelli Dec 6, 2024
4db6b39
fix(wazuh-api): replace WAZUH_ERROR_CODES with WAZUH_ERROR_DAEMONS_NO…
guidomodarelli Dec 9, 2024
808d3be
fix(constants): rename pluginPlatformRequestHeaders to PLUGIN_PLATFOR…
guidomodarelli Dec 9, 2024
342f4ea
fix(constants): refactor query language constants and improve code co…
guidomodarelli Dec 9, 2024
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
17 changes: 17 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"diffEditor.ignoreTrimWhitespace": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.inlineSuggest.enabled": true,
"editor.insertSpaces": true,
"editor.minimap.enabled": true,
"editor.rulers": [80, 100],
"editor.tabSize": 2,
"editor.trimAutoWhitespace": true,
"editor.wordWrap": "on",
"explorer.confirmDelete": true,
"files.autoSave": "off",
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.updateImportsOnFileMove.enabled": "always"
}
13 changes: 3 additions & 10 deletions plugins/main/server/controllers/wazuh-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,9 @@ export class WazuhApiCtrl {
}
}
}
let token;
if (context.wazuh_core.manageHosts.isEnabledAuthWithRunAs(idHost)) {
token = await context.wazuh.api.client.asCurrentUser.authenticate(
idHost,
);
} else {
token = await context.wazuh.api.client.asInternalUser.authenticate(
idHost,
);
}
const token = await context.wazuh.api.client.asCurrentUser.authenticate(
idHost,
);

let textSecure = '';
if (context.wazuh.server.info.protocol === 'https') {
Expand Down
4 changes: 2 additions & 2 deletions plugins/wazuh-core/common/services/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { cloneDeep } from 'lodash';
import { formatLabelValuePair } from './settings';
import { formatBytes } from './file-size';

export interface ILogger {
export interface Logger {
debug(message: string): void;
info(message: string): void;
warn(message: string): void;
Expand Down Expand Up @@ -180,7 +180,7 @@ export class Configuration implements IConfiguration {
store: IConfigurationStore | null = null;
_settings: Map<string, { [key: string]: TConfigurationSetting }>;
_categories: Map<string, { [key: string]: any }>;
constructor(private logger: ILogger, store: IConfigurationStore) {
constructor(private logger: Logger, store: IConfigurationStore) {
this._settings = new Map();
this._categories = new Map();
this.setStore(store);
Expand Down
26 changes: 25 additions & 1 deletion plugins/wazuh-core/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '../common/constants';
import { DashboardSecurity } from './utils/dashboard-security';
import * as hooks from './hooks';
import { CoreHTTPClient } from './services/http/http-client';

export class WazuhCorePlugin
implements Plugin<WazuhCorePluginSetup, WazuhCorePluginStart>
Expand All @@ -19,12 +20,21 @@ export class WazuhCorePlugin
services: { [key: string]: any } = {};
public async setup(core: CoreSetup): Promise<WazuhCorePluginSetup> {
const noop = () => {};
const logger = {
// Debug logger
const consoleLogger = {
info: console.log,
error: console.error,
debug: console.debug,
warn: console.warn,
};
// No operation logger
const noopLogger = {
Desvelao marked this conversation as resolved.
Show resolved Hide resolved
info: noop,
error: noop,
debug: noop,
warn: noop,
};
const logger = noopLogger;
this._internal.configurationStore = new ConfigurationStore(
logger,
core.http,
Expand All @@ -44,9 +54,22 @@ export class WazuhCorePlugin
this.services.configuration.registerCategory({ ...value, id: key });
});

// Create dashboardSecurity
this.services.dashboardSecurity = new DashboardSecurity(logger, core.http);

// Create http
this.services.http = new CoreHTTPClient(logger, {
getTimeout: async () =>
(await this.services.configuration.get('timeout')) as number,
getURL: (path: string) => core.http.basePath.prepend(path),
getServerAPI: () => 'api-host-id', // TODO: implement
getIndexPatternTitle: async () => 'wazuh-alerts-*', // TODO: implement
http: core.http,
});

// Setup services
await this.services.dashboardSecurity.setup();
await this.services.http.setup();

return {
...this.services,
Expand All @@ -60,6 +83,7 @@ export class WazuhCorePlugin
setCore(core);
setUiSettings(core.uiSettings);

// Start services
await this.services.configuration.start({ http: core.http });

return {
Expand Down
105 changes: 105 additions & 0 deletions plugins/wazuh-core/public/services/http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# HTTPClient

The `HTTPClient` provides a custom mechanim to do an API request to the backend side.

This defines a request interceptor that disables the requests when `core.http` returns a response with status code 401, avoiding a problem in the login flow (with SAML).

The request interceptor is used in the clients:

- generic
- server

## Generic

This client provides a method to run the request that injects some properties related to an index pattern and selected server API host in the headers of the API request that could be used for some backend endpoints

### Usage

#### Request

```ts
plugins.wazuhCore.http.request('GET', '/api/check-api', {});
```

## Server

This client provides:

- some methods to communicate with the Wazuh server API
- manage authentication with Wazuh server API
- store the login data

### Usage

#### Authentication

```ts
plugins.wazuhCore.http.auth();
```

#### Unauthentication

```ts
plugins.wazuhCore.http.unauth();
```

#### Request

```ts
plugins.wazuhCore.http.request('GET', '/agents', {});
```

#### CSV

```ts
plugins.wazuhCore.http.csv('GET', '/agents', {});
```

#### Check API id

```ts
plugins.wazuhCore.http.checkApiById('api-host-id');
```

#### Check API

```ts
plugins.wazuhCore.http.checkApi(apiHostData);
```

#### Get user data

```ts
plugins.wazuhCore.http.getUserData();
```

The changes in the user data can be retrieved thourgh the `userData$` observable.

```ts
plugins.wazuhCore.http.userData$.subscribe(userData => {
// do something with the data
});
```

### Register interceptor

In each application when this is mounted through the `mount` method, the request interceptor must be registered and when the application is unmounted must be unregistered.

> We should research about the possibility to register/unregister the interceptor once in the `wazuh-core` plugin instead of registering/unregisting in each mount of application.

```ts
// setup lifecycle plugin method

// Register an application
core.application.register({
// rest of registration properties
mount: () => {
// Register the interceptor
plugins.wazuhCore.http.register();
return () => {
// Unregister the interceptor
plugins.wazuhCore.http.unregister();
};
},
});
```
5 changes: 5 additions & 0 deletions plugins/wazuh-core/public/services/http/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const PLUGIN_PLATFORM_REQUEST_HEADERS = {
'osd-xsrf': 'kibana',
};

export const HTTP_CLIENT_DEFAULT_TIMEOUT = 20000;
127 changes: 127 additions & 0 deletions plugins/wazuh-core/public/services/http/generic-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { PLUGIN_PLATFORM_REQUEST_HEADERS } from './constants';
import { Logger } from '../../../common/services/configuration';
import {
HTTPClientGeneric,
HTTPClientRequestInterceptor,
HTTPVerb,
} from './types';

interface GenericRequestServices {
request: HTTPClientRequestInterceptor['request'];
getURL(path: string): string;
getTimeout(): Promise<number>;
getIndexPatternTitle(): Promise<string>;
getServerAPI(): string;
checkAPIById(apiId: string): Promise<any>;
}

export class GenericRequest implements HTTPClientGeneric {
onErrorInterceptor?: (error: any) => Promise<void>;
constructor(
private logger: Logger,
private services: GenericRequestServices,
) {}
async request(
method: HTTPVerb,
path: string,
payload = null,
returnError = false,
) {
try {
if (!method || !path) {
throw new Error('Missing parameters');
}
const timeout = await this.services.getTimeout();
const requestHeaders = {
...PLUGIN_PLATFORM_REQUEST_HEADERS,
'content-type': 'application/json',
};
const url = this.services.getURL(path);

try {
requestHeaders.pattern = await this.services.getIndexPatternTitle();
} catch (error) {}

try {
requestHeaders.id = this.services.getServerAPI();
} catch (error) {
// Intended
}
var options = {};

if (method === 'GET') {
options = {
method: method,
headers: requestHeaders,
url: url,
timeout: timeout,
};
}
if (method === 'PUT') {
options = {
method: method,
headers: requestHeaders,
data: payload,
url: url,
timeout: timeout,
};
}
if (method === 'POST') {
options = {
method: method,
headers: requestHeaders,
data: payload,
url: url,
timeout: timeout,
};
}
if (method === 'DELETE') {
options = {
method: method,
headers: requestHeaders,
data: payload,
url: url,
timeout: timeout,
};
}

const data = await this.services.request(options);
if (!data) {
throw new Error(`Error doing a request to ${url}, method: ${method}.`);
}

return data;
} catch (error) {
//if the requests fails, we need to check if the API is down
const currentApi = this.services.getServerAPI(); //JSON.parse(AppState.getCurrentAPI() || '{}');
if (currentApi) {
try {
await this.services.checkAPIById(currentApi);
} catch (err) {
// const wzMisc = new WzMisc();
// wzMisc.setApiIsDown(true);
// if (
// ['/settings', '/health-check', '/blank-screen'].every(
// pathname =>
// !NavigationService.getInstance()
// .getPathname()
// .startsWith(pathname),
// )
// ) {
// NavigationService.getInstance().navigate('/health-check');
// }
}
}
// if(this.onErrorInterceptor){
// await this.onErrorInterceptor(error)
// }
if (returnError) return Promise.reject(error);
return (((error || {}).response || {}).data || {}).message || false
? Promise.reject(new Error(error.response.data.message))
: Promise.reject(error || new Error('Server did not respond'));
}
}
setOnErrorInterceptor(onErrorInterceptor: (error: any) => Promise<void>) {
this.onErrorInterceptor = onErrorInterceptor;
}
}
Loading
Loading