Skip to content

Commit

Permalink
[Multiple DataSource] Add support for SigV4 authentication
Browse files Browse the repository at this point in the history
Signed-off-by: Su <[email protected]>
  • Loading branch information
zhongnansu committed Feb 8, 2023
1 parent d9dc91d commit 1b658a8
Show file tree
Hide file tree
Showing 18 changed files with 1,257 additions and 204 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Optimizer] Increase timeout waiting for the exiting of an optimizer worker ([#3193](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3193))
- [Data] Update `createAggConfig` so that newly created configs can be added to beginning of `aggConfig` array ([#3160](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3160))
- Add disablePrototypePoisoningProtection configuration to prevent JS client from erroring when cluster utilizes JS reserved words ([#2992](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2992))
- [Multiple DataSource] Add support for SigV4 authentication ([#3058](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/3058))

### 🐛 Bug Fixes

Expand Down
2 changes: 1 addition & 1 deletion config/opensearch_dashboards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@

# Set the value of this setting to true to enable the experimental multiple data source
# support feature. Use with caution.
#data_source.enabled: false
data_source.enabled: true
# Set the value of these settings to customize crypto materials to encryption saved credentials
# in data sources.
#data_source.encryption.wrappingKeyName: 'changeme'
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
"@hapi/podium": "^4.1.3",
"@hapi/vision": "^6.1.0",
"@hapi/wreck": "^17.1.0",
"@opensearch-project/opensearch": "^1.1.0",
"@opensearch-project/opensearch": "^2.1.0",
"@osd/ace": "1.0.0",
"@osd/analytics": "1.0.0",
"@osd/apm-config-loader": "1.0.0",
Expand Down Expand Up @@ -166,6 +166,7 @@
"dns-sync": "^0.2.1",
"elastic-apm-node": "^3.7.0",
"elasticsearch": "^16.7.0",
"http-aws-es": "6.0.0",
"execa": "^4.0.2",
"expiry-js": "0.1.7",
"fast-deep-equal": "^3.1.1",
Expand Down Expand Up @@ -334,6 +335,7 @@
"@types/zen-observable": "^0.8.0",
"@typescript-eslint/eslint-plugin": "^3.10.0",
"@typescript-eslint/parser": "^3.10.0",
"@types/http-aws-es": "6.0.2",
"angular-aria": "^1.8.0",
"angular-mocks": "^1.8.2",
"angular-recursion": "^1.0.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/osd-opensearch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"osd:watch": "node scripts/build --watch"
},
"dependencies": {
"@opensearch-project/opensearch": "^1.1.0",
"@opensearch-project/opensearch": "^2.1.0",
"@osd/dev-utils": "1.0.0",
"abort-controller": "^3.0.0",
"chalk": "^4.1.0",
Expand Down
2 changes: 2 additions & 0 deletions src/dev/jest/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export default {
moduleNameMapper: {
'@elastic/eui$': '<rootDir>/node_modules/@elastic/eui/test-env',
'@elastic/eui/lib/(.*)?': '<rootDir>/node_modules/@elastic/eui/test-env/$1',
'@opensearch-project/opensearch/aws':
'<rootDir>/node_modules/@opensearch-project/opensearch/lib/aws',
'^src/plugins/(.*)': '<rootDir>/src/plugins/$1',
'^test_utils/(.*)': '<rootDir>/src/test_utils/public/$1',
'^fixtures/(.*)': '<rootDir>/src/fixtures/$1',
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/data_source/common/data_sources/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ export interface DataSourceAttributes extends SavedObjectAttributes {
endpoint: string;
auth: {
type: AuthType;
credentials: UsernamePasswordTypedContent | undefined;
credentials: UsernamePasswordTypedContent | SigV4Content | undefined;
};
lastUpdatedTime?: string;
}

export interface SigV4Content extends SavedObjectAttributes {
accessKey: string;
secretKey: string;
region: string;
}

export interface UsernamePasswordTypedContent extends SavedObjectAttributes {
Expand All @@ -23,4 +30,5 @@ export interface UsernamePasswordTypedContent extends SavedObjectAttributes {
export enum AuthType {
NoAuth = 'no_auth',
UsernamePasswordType = 'username_password',
SigV4 = 'sigv4',
}
46 changes: 37 additions & 9 deletions src/plugins/data_source/server/client/client_pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import { Client } from '@opensearch-project/opensearch';
import { Client as LegacyClient } from 'elasticsearch';
import LRUCache from 'lru-cache';
import { Logger } from 'src/core/server';
import { AuthType } from '../../common/data_sources';
import { DataSourcePluginConfigType } from '../../config';

export interface OpenSearchClientPoolSetup {
getClientFromPool: (id: string) => Client | LegacyClient | undefined;
addClientToPool: (endpoint: string, client: Client | LegacyClient) => void;
getClientFromPool: (endpoint: string, authType: AuthType) => Client | LegacyClient | undefined;
addClientToPool: (endpoint: string, authType: AuthType, client: Client | LegacyClient) => void;
}

/**
Expand All @@ -24,7 +25,8 @@ export class OpenSearchClientPool {
// LRU cache
// key: data source endpoint
// value: OpenSearch client object | Legacy client object
private cache?: LRUCache<string, Client | LegacyClient>;
private clientCache?: LRUCache<string, Client | LegacyClient>;
private awsClientCache?: LRUCache<string, Client | LegacyClient>;
private isClosed = false;

constructor(private logger: Logger) {}
Expand All @@ -33,7 +35,7 @@ export class OpenSearchClientPool {
const logger = this.logger;
const { size } = config.clientPool;

this.cache = new LRUCache({
this.clientCache = new LRUCache({
max: size,
maxAge: 15 * 60 * 1000, // by default, TCP connection times out in 15 minutes

Expand All @@ -50,12 +52,35 @@ export class OpenSearchClientPool {
});
this.logger.info(`Created data source client pool of size ${size}`);

const getClientFromPool = (endpoint: string) => {
return this.cache!.get(endpoint);
// aws client specific pool
this.awsClientCache = new LRUCache({
max: size,
maxAge: 15 * 60 * 1000, // by default, TCP connection times out in 15 minutes

async dispose(endpoint, client) {
try {
await client.close();
} catch (error: any) {
// log and do nothing since we are anyways evicting the client object from cache
logger.warn(
`Error closing OpenSearch client when removing from aws client pool: ${error.message}`
);
}
},
});
this.logger.info(`Created data source aws client pool of size ${size}`);

const getClientFromPool = (endpoint: string, authType: AuthType) => {
const selectedCache = authType === AuthType.SigV4 ? this.awsClientCache : this.clientCache;

return selectedCache!.get(endpoint);
};

const addClientToPool = (endpoint: string, client: Client | LegacyClient) => {
this.cache!.set(endpoint, client);
const addClientToPool = (endpoint: string, authType: string, client: Client | LegacyClient) => {
const selectedCache = authType === AuthType.SigV4 ? this.awsClientCache : this.clientCache;
if (!selectedCache?.has(endpoint)) {
return selectedCache!.set(endpoint, client);
}
};

return {
Expand All @@ -71,7 +96,10 @@ export class OpenSearchClientPool {
if (this.isClosed) {
return;
}
await Promise.all(this.cache!.values().map((client) => client.close()));
await Promise.all([
...this.clientCache!.values().map((client) => client.close()),
...this.awsClientCache!.values().map((client) => client.close()),
]);
this.isClosed = true;
}
}
Loading

0 comments on commit 1b658a8

Please sign in to comment.