From ccf75dac3111a3113510ccc74908b20871b53eaf Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Wed, 20 Jul 2022 13:26:06 -0700 Subject: [PATCH 1/7] Move generate_crypto_materials to /script --- package.json | 3 +- .../crypto_materials_generator.js | 7 ++++- src/plugins/credential_management/README.md | 13 +++----- ...rypto_materials_generator.ts => config.ts} | 8 +++-- .../crypto/{cli/crypto_cli.ts => cli.ts} | 31 ++++++++++--------- .../server/crypto/index.ts | 2 +- 6 files changed, 35 insertions(+), 29 deletions(-) rename src/plugins/credential_management/server/crypto/cli/index.ts => scripts/crypto_materials_generator.js (57%) rename src/plugins/credential_management/{server/crypto/crypto_materials_generator.ts => config.ts} (59%) rename src/plugins/credential_management/server/crypto/{cli/crypto_cli.ts => cli.ts} (82%) diff --git a/package.json b/package.json index 86d3218b17c3..9b50cdba8f08 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,8 @@ "docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept", "osd:bootstrap": "node scripts/build_ts_refs && node scripts/register_git_hook", "spec_to_console": "node scripts/spec_to_console", - "pkg-version": "./dev-tools/get-version.sh" + "pkg-version": "./dev-tools/get-version.sh", + "generate-crypto-materials": "node scripts/crypto_materials_generator" }, "repository": { "type": "git", diff --git a/src/plugins/credential_management/server/crypto/cli/index.ts b/scripts/crypto_materials_generator.js similarity index 57% rename from src/plugins/credential_management/server/crypto/cli/index.ts rename to scripts/crypto_materials_generator.js index 10af40768fba..b94a312d98f1 100644 --- a/src/plugins/credential_management/server/crypto/cli/index.ts +++ b/scripts/crypto_materials_generator.js @@ -9,4 +9,9 @@ * GitHub history for details. */ -export { CryptoCli } from './crypto_cli'; +require('../src/setup_node_env'); + +var args = require('yargs').argv; +var { generateCryptoMaterials } = require('../src/plugins/credential_management/server/crypto'); + +generateCryptoMaterials(args.keyName, args.keyNamespace); diff --git a/src/plugins/credential_management/README.md b/src/plugins/credential_management/README.md index 6bb784b530a5..473cae2ae664 100755 --- a/src/plugins/credential_management/README.md +++ b/src/plugins/credential_management/README.md @@ -14,12 +14,9 @@ setting up your development environment. ## Build and Run crypto_materials_generator ``` -npm install @types/yargs -npm install -g ts-node typescript '@types/node' -``` - -``` -cd - -ts-node src/plugins/credential_management/server/crypto/crypto_materials_generator.ts --keyName='aes-name' --keyNamespace='aes-namespace' +% yarn generate-crypto-materials --keyName='aes-name' --keyNamespace='aes-namespace' +yarn run v1.22.19 +$ node scripts/crypto_materials_generator --keyName=aes-name --keyNamespace=aes-namespace +Crypto materials generated! +✨ Done in 1.86s. ``` diff --git a/src/plugins/credential_management/server/crypto/crypto_materials_generator.ts b/src/plugins/credential_management/config.ts similarity index 59% rename from src/plugins/credential_management/server/crypto/crypto_materials_generator.ts rename to src/plugins/credential_management/config.ts index f41241de94d8..1e40d67e3adb 100644 --- a/src/plugins/credential_management/server/crypto/crypto_materials_generator.ts +++ b/src/plugins/credential_management/config.ts @@ -9,8 +9,10 @@ * GitHub history for details. */ -import { CryptoCli } from './cli'; +import { schema, TypeOf } from '@osd/config-schema'; -const args = require('yargs').argv; +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), +}); -CryptoCli.generateCryptoMaterials(args.keyName, args.keyNamespace); +export type ConfigSchema = TypeOf; diff --git a/src/plugins/credential_management/server/crypto/cli/crypto_cli.ts b/src/plugins/credential_management/server/crypto/cli.ts similarity index 82% rename from src/plugins/credential_management/server/crypto/cli/crypto_cli.ts rename to src/plugins/credential_management/server/crypto/cli.ts index e07461239c5f..0a8eef202ace 100644 --- a/src/plugins/credential_management/server/crypto/cli/crypto_cli.ts +++ b/src/plugins/credential_management/server/crypto/cli.ts @@ -79,19 +79,20 @@ export class CryptoCli { // Return Default Path return './crypto_material'; } - - // TODO: Support configurable crypto materials file path - public static generateCryptoMaterials(keyName: string, keyNamespace: string) { - const cryptoMaterials = { - keyName, - keyNamespace, - unencryptedMasterKey: randomBytes(32), - }; - const path = CryptoCli.loadConfigAndGetPath('config/credential_management.yml'); - - writeFile(path, JSON.stringify(cryptoMaterials), function (err) { - if (err) throw err; - }); - // console.info('crypto materials generated successfully!'); - } } + +const generateCryptoMaterials = function (keyName: string, keyNamespace: string) { + const cryptoMaterials = { + keyName, + keyNamespace, + unencryptedMasterKey: randomBytes(32), + }; + const path = CryptoCli.loadConfigAndGetPath('config/credential_management.yml'); + + writeFile(path, JSON.stringify(cryptoMaterials), function (err) { + if (err) throw err; + }); + console.log('Crypto materials generated!'); +}; + +export { generateCryptoMaterials }; \ No newline at end of file diff --git a/src/plugins/credential_management/server/crypto/index.ts b/src/plugins/credential_management/server/crypto/index.ts index bc9590b1c1fb..133241b23cb6 100644 --- a/src/plugins/credential_management/server/crypto/index.ts +++ b/src/plugins/credential_management/server/crypto/index.ts @@ -9,4 +9,4 @@ * GitHub history for details. */ -export { CryptoCli } from './cli/index'; +export { CryptoCli, generateCryptoMaterials } from './cli'; From 964367a1bae4dc63ce25f133b075aa8e70660d89 Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Wed, 20 Jul 2022 15:18:22 -0700 Subject: [PATCH 2/7] Add cm configs to osd.yml --- config/credential_management.yml | 1 - config/opensearch_dashboards.yml | 5 +++ src/plugins/credential_management/config.ts | 1 + .../service/credential_management_service.ts | 1 + .../server/config_manager/config_manager.ts | 43 +++++++++++++++++++ .../server/config_manager/index.ts | 0 .../credential_manager.ts | 0 .../index.ts | 0 .../server/crypto/cli.ts | 30 +++++-------- .../credential_management/server/plugin.ts | 18 ++++---- .../server/routes/create.ts | 2 +- .../server/routes/update.ts | 2 +- 12 files changed, 72 insertions(+), 31 deletions(-) delete mode 100644 config/credential_management.yml create mode 100644 src/plugins/credential_management/server/config_manager/config_manager.ts create mode 100644 src/plugins/credential_management/server/config_manager/index.ts rename src/plugins/credential_management/server/{credential => credential_manager}/credential_manager.ts (100%) rename src/plugins/credential_management/server/{credential => credential_manager}/index.ts (100%) diff --git a/config/credential_management.yml b/config/credential_management.yml deleted file mode 100644 index b3d2943fbe49..000000000000 --- a/config/credential_management.yml +++ /dev/null @@ -1 +0,0 @@ -multiDataSource.materialPath: "src/plugins/credential_management/server/crypto/crypto_material" \ No newline at end of file diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml index 162545b2a1a5..4e5945025149 100644 --- a/config/opensearch_dashboards.yml +++ b/config/opensearch_dashboards.yml @@ -183,3 +183,8 @@ # Set the value of this setting to false to suppress search usage telemetry # for reducing the load of OpenSearch cluster. # data.search.usageTelemetry.enabled: false + +# Set the value of this setting to true to enable credential management for managing +# the credentials of OpenSearch cluster. +# credentialManagement.enabled: true +# credentialManagement.materialPath: "src/plugins/credential_management/server/crypto/crypto_material" diff --git a/src/plugins/credential_management/config.ts b/src/plugins/credential_management/config.ts index 1e40d67e3adb..653530f9e59b 100644 --- a/src/plugins/credential_management/config.ts +++ b/src/plugins/credential_management/config.ts @@ -13,6 +13,7 @@ import { schema, TypeOf } from '@osd/config-schema'; export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), + materialPath: schema.string({ defaultValue: "src/plugins/credential_management/server/crypto/crypto_material" }), }); export type ConfigSchema = TypeOf; diff --git a/src/plugins/credential_management/public/service/credential_management_service.ts b/src/plugins/credential_management/public/service/credential_management_service.ts index e86b392ed091..058446e0c460 100644 --- a/src/plugins/credential_management/public/service/credential_management_service.ts +++ b/src/plugins/credential_management/public/service/credential_management_service.ts @@ -12,6 +12,7 @@ import { HttpSetup } from '../../../../core/public'; import { CredentialCreationConfig, CredentialCreationManager } from './creation'; + interface SetupDependencies { httpClient: HttpSetup; } diff --git a/src/plugins/credential_management/server/config_manager/config_manager.ts b/src/plugins/credential_management/server/config_manager/config_manager.ts new file mode 100644 index 000000000000..b271b02510f6 --- /dev/null +++ b/src/plugins/credential_management/server/config_manager/config_manager.ts @@ -0,0 +1,43 @@ +// /* +// * SPDX-License-Identifier: Apache-2.0 +// * +// * The OpenSearch Contributors require contributions made to +// * this file be licensed under the Apache-2.0 license or a +// * compatible open source license. +// * +// * Any modifications Copyright OpenSearch Contributors. See +// * GitHub history for details. +// */ + +// import { PluginInitializerContext } from 'opensearch-dashboards/server'; +// import { TypeOf } from '@osd/config-schema'; +// import { configSchema } from '../../config'; + +// export class ConfigManager { +// private opensearchShardTimeout: number = 0; +// private graphiteAllowedUrls: string[] = []; +// private graphiteBlockedIPs: string[] = []; + +// constructor(config: PluginInitializerContext['config']) { +// config.create>().subscribe((configUpdate) => { +// this.graphiteAllowedUrls = configUpdate.graphiteAllowedUrls || []; +// this.graphiteBlockedIPs = configUpdate.graphiteBlockedIPs || []; +// }); + +// config.legacy.globalConfig$.subscribe((configUpdate) => { +// this.opensearchShardTimeout = configUpdate.opensearch.shardTimeout.asMilliseconds(); +// }); +// } + +// getOpenSearchShardTimeout() { +// return this.opensearchShardTimeout; +// } + +// getGraphiteAllowedUrls() { +// return this.graphiteAllowedUrls; +// } + +// getGraphiteBlockedIPs() { +// return this.graphiteBlockedIPs; +// } +// } diff --git a/src/plugins/credential_management/server/config_manager/index.ts b/src/plugins/credential_management/server/config_manager/index.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/plugins/credential_management/server/credential/credential_manager.ts b/src/plugins/credential_management/server/credential_manager/credential_manager.ts similarity index 100% rename from src/plugins/credential_management/server/credential/credential_manager.ts rename to src/plugins/credential_management/server/credential_manager/credential_manager.ts diff --git a/src/plugins/credential_management/server/credential/index.ts b/src/plugins/credential_management/server/credential_manager/index.ts similarity index 100% rename from src/plugins/credential_management/server/credential/index.ts rename to src/plugins/credential_management/server/credential_manager/index.ts diff --git a/src/plugins/credential_management/server/crypto/cli.ts b/src/plugins/credential_management/server/crypto/cli.ts index 0a8eef202ace..81c04208a6d4 100644 --- a/src/plugins/credential_management/server/crypto/cli.ts +++ b/src/plugins/credential_management/server/crypto/cli.ts @@ -18,7 +18,8 @@ import { import { randomBytes } from 'crypto'; import { readFileSync, writeFile } from 'fs'; -import { safeLoad } from 'js-yaml'; + +const defaultPath = "src/plugins/credential_management/server/crypto/crypto_material"; export class CryptoCli { private static _instance: CryptoCli; @@ -28,12 +29,14 @@ export class CryptoCli { private readonly _encrypt; private readonly _decrypt; - private constructor() { + private constructor(path: string) { const wrappingSuite = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING; // TODO: Move config to opensearch_dashboards.yam and load config during bootstrap // TODO: Generate materials by default during bootstrap + + // TODO: Add path validation with default calling generateCryptoMaterials const cryptoMaterials = JSON.parse( - readFileSync(CryptoCli.loadConfigAndGetPath('config/credential_management.yml'), 'utf8') + readFileSync(path, 'utf8') ); const input = { @@ -61,33 +64,22 @@ export class CryptoCli { return result.plaintext.toString(); } - public static getInstance(): CryptoCli { + // TODO: Append CryptoCli.getInstance into plugin lifecycle + public static getInstance(path=defaultPath): CryptoCli { if (!CryptoCli._instance) { - CryptoCli._instance = new CryptoCli(); + CryptoCli._instance = new CryptoCli(path); } return CryptoCli._instance; } - - // TODO: Fine grain config loader - public static loadConfigAndGetPath(path: string): string { - const yaml = safeLoad(readFileSync(path, 'utf8')); - if (yaml !== null && typeof yaml === 'object') { - return JSON.parse(JSON.stringify(yaml))['multiDataSource.materialPath']; - } - // console.error('Load failed! Please check the config path.'); - // Return Default Path - return './crypto_material'; - } } -const generateCryptoMaterials = function (keyName: string, keyNamespace: string) { +const generateCryptoMaterials = function (keyName: string, keyNamespace: string, path=defaultPath) { const cryptoMaterials = { keyName, keyNamespace, unencryptedMasterKey: randomBytes(32), }; - const path = CryptoCli.loadConfigAndGetPath('config/credential_management.yml'); writeFile(path, JSON.stringify(cryptoMaterials), function (err) { if (err) throw err; @@ -95,4 +87,4 @@ const generateCryptoMaterials = function (keyName: string, keyNamespace: string) console.log('Crypto materials generated!'); }; -export { generateCryptoMaterials }; \ No newline at end of file +export { generateCryptoMaterials }; diff --git a/src/plugins/credential_management/server/plugin.ts b/src/plugins/credential_management/server/plugin.ts index 521c9f88ffed..934132f88151 100644 --- a/src/plugins/credential_management/server/plugin.ts +++ b/src/plugins/credential_management/server/plugin.ts @@ -10,27 +10,30 @@ */ import { - PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger, } from '../../../core/server'; +import { PluginInitializerContext } from 'src/core/public'; + import { CredentialManagementPluginSetup, CredentialManagementPluginStart } from './types'; import { registerRoutes } from './routes'; import { credentialSavedObjectType } from './saved_objects'; +import { ConfigSchema } from '../config'; +import { CryptoCli } from './crypto'; export class CredentialManagementPlugin implements Plugin { - private readonly logger: Logger; + private cryptoCli: CryptoCli; - constructor(initializerContext: PluginInitializerContext) { - this.logger = initializerContext.logger.get(); + constructor(initializerContext: PluginInitializerContext) { + const { materialPath } = initializerContext.config.get(); + this.cryptoCli = CryptoCli.getInstance(materialPath); } public setup(core: CoreSetup) { - this.logger.debug('credentialManagement: Setup'); const router = core.http.createRouter(); // Register server side APIs @@ -43,11 +46,8 @@ export class CredentialManagementPlugin } public start(core: CoreStart) { - this.logger.debug('credentialManagement: Started'); return {}; } - public stop() { - this.logger.debug('credentialManagement: Stoped'); - } + public stop() {} } diff --git a/src/plugins/credential_management/server/routes/create.ts b/src/plugins/credential_management/server/routes/create.ts index 93183f8ead74..801cbca5d3dd 100644 --- a/src/plugins/credential_management/server/routes/create.ts +++ b/src/plugins/credential_management/server/routes/create.ts @@ -10,7 +10,7 @@ */ import { schema } from '@osd/config-schema'; import { IRouter } from '../../../../core/server'; -import { encryptionHandler } from '../credential'; +import { encryptionHandler } from '../credential_manager'; import { Credential } from '../../common'; const USERNAME_PASSWORD_TYPE: Credential.USERNAME_PASSWORD_TYPE = 'username_password_credential'; diff --git a/src/plugins/credential_management/server/routes/update.ts b/src/plugins/credential_management/server/routes/update.ts index af0de411e076..32cff3b19067 100644 --- a/src/plugins/credential_management/server/routes/update.ts +++ b/src/plugins/credential_management/server/routes/update.ts @@ -10,7 +10,7 @@ */ import { schema } from '@osd/config-schema'; import { IRouter } from '../../../../core/server'; -import { encryptionHandler } from '../credential'; +import { encryptionHandler } from '../credential_manager'; import { Credential } from '../../common'; const USERNAME_PASSWORD_TYPE: Credential.USERNAME_PASSWORD_TYPE = 'username_password_credential'; From 7778029852476fd4ebbe8eb01dca4839ea0d68ea Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Thu, 21 Jul 2022 05:06:19 -0700 Subject: [PATCH 3/7] Create default crypto material during plugin setup --- src/plugins/credential_management/config.ts | 6 +++-- .../opensearch_dashboards.json | 1 + .../credential_management/server/plugin.ts | 22 +++++++++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/plugins/credential_management/config.ts b/src/plugins/credential_management/config.ts index 653530f9e59b..506c04ebe422 100644 --- a/src/plugins/credential_management/config.ts +++ b/src/plugins/credential_management/config.ts @@ -12,8 +12,10 @@ import { schema, TypeOf } from '@osd/config-schema'; export const configSchema = schema.object({ - enabled: schema.boolean({ defaultValue: true }), - materialPath: schema.string({ defaultValue: "src/plugins/credential_management/server/crypto/crypto_material" }), + enabled: schema.boolean({ defaultValue: false }), + materialPath: schema.string({ + defaultValue: 'src/plugins/credential_management/server/crypto/crypto_material', + }), }); export type ConfigSchema = TypeOf; diff --git a/src/plugins/credential_management/opensearch_dashboards.json b/src/plugins/credential_management/opensearch_dashboards.json index fb3eca7a63a0..061ae6e39677 100644 --- a/src/plugins/credential_management/opensearch_dashboards.json +++ b/src/plugins/credential_management/opensearch_dashboards.json @@ -2,6 +2,7 @@ "id": "credentialManagement", "version": "1.0.0", "opensearchDashboardsVersion": "opensearchDashboards", + "configPath": ["credential_management"], "server": true, "ui": true, "requiredPlugins": ["management", "data", "navigation", "urlForwarding"], diff --git a/src/plugins/credential_management/server/plugin.ts b/src/plugins/credential_management/server/plugin.ts index 934132f88151..163972ff9dba 100644 --- a/src/plugins/credential_management/server/plugin.ts +++ b/src/plugins/credential_management/server/plugin.ts @@ -8,16 +8,16 @@ * Any modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ +import { first } from 'rxjs/operators'; import { + PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger, } from '../../../core/server'; -import { PluginInitializerContext } from 'src/core/public'; - import { CredentialManagementPluginSetup, CredentialManagementPluginStart } from './types'; import { registerRoutes } from './routes'; import { credentialSavedObjectType } from './saved_objects'; @@ -25,15 +25,20 @@ import { ConfigSchema } from '../config'; import { CryptoCli } from './crypto'; export class CredentialManagementPlugin - implements Plugin { - private cryptoCli: CryptoCli; + implements Plugin +{ + private readonly logger: Logger; + private initializerContext: PluginInitializerContext; + + private cryptoCli?: CryptoCli; constructor(initializerContext: PluginInitializerContext) { - const { materialPath } = initializerContext.config.get(); - this.cryptoCli = CryptoCli.getInstance(materialPath); + this.logger = initializerContext.logger.get(); + this.initializerContext = initializerContext; } - public setup(core: CoreSetup) { + public async setup(core: CoreSetup) { + this.logger.debug('credential_management: Setup'); const router = core.http.createRouter(); // Register server side APIs @@ -42,6 +47,9 @@ export class CredentialManagementPlugin // Register credential saved object type core.savedObjects.registerType(credentialSavedObjectType); + const config = await this.initializerContext.config.create().pipe(first()).toPromise(); + this.logger.debug('Config: ' + config.enabled); + return {}; } From 9429f334d6f5d4375c8c52f9f4780e5a4b4c4bb4 Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Thu, 21 Jul 2022 11:41:29 -0700 Subject: [PATCH 4/7] Resolve path issue --- config/opensearch_dashboards.yml | 6 ++- src/plugins/credential_management/README.md | 29 +++++++++++-- src/plugins/credential_management/config.ts | 2 +- .../server/config_manager/config_manager.ts | 43 ------------------- .../server/config_manager/index.ts | 0 .../server/crypto/cli.ts | 38 +++++++++------- .../credential_management/server/index.ts | 9 +++- .../credential_management/server/plugin.ts | 28 ++++++------ 8 files changed, 75 insertions(+), 80 deletions(-) delete mode 100644 src/plugins/credential_management/server/config_manager/config_manager.ts delete mode 100644 src/plugins/credential_management/server/config_manager/index.ts diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml index 4e5945025149..44d203726005 100644 --- a/config/opensearch_dashboards.yml +++ b/config/opensearch_dashboards.yml @@ -186,5 +186,7 @@ # Set the value of this setting to true to enable credential management for managing # the credentials of OpenSearch cluster. -# credentialManagement.enabled: true -# credentialManagement.materialPath: "src/plugins/credential_management/server/crypto/crypto_material" +# It's enabled now for for playground env CD +# TODO: Disable it for release +credential_management.enabled: true +# credential_management.materialPath: "path/to/your/crypto_material" diff --git a/src/plugins/credential_management/README.md b/src/plugins/credential_management/README.md index 473cae2ae664..4287b40db7d4 100755 --- a/src/plugins/credential_management/README.md +++ b/src/plugins/credential_management/README.md @@ -10,13 +10,34 @@ See the [OpenSearch Dashboards contributing guide](https://github.com/opensearch-project/OpenSearch-Dashboards/blob/master/CONTRIBUTING.md) for instructions setting up your development environment. +## Configuration -## Build and Run crypto_materials_generator +1. To enable this feature, override config/opensearch_dashboards.yml ``` -% yarn generate-crypto-materials --keyName='aes-name' --keyNamespace='aes-namespace' +credential_management.enabled: true +``` + +2. To setup path for crypto material, override config/opensearch_dashboards.yml + +``` +credential_management.materialPath: "path/to/your/crypto_material" +``` + +## Generate your own crypto material via crypto_materials_generator script + +``` +yarn generate-crypto-materials --path='path/to/your/crypto_material' --keyName='aes-name' --keyNamespace='aes-namespace' + +// Expected Output + +% yarn generate-crypto-materials --path='data/crypto_material' --keyName='aes-name' --keyNamespace='aes-namespace' + yarn run v1.22.19 -$ node scripts/crypto_materials_generator --keyName=aes-name --keyNamespace=aes-namespace +$ node scripts/crypto_materials_generator --path=data/crypto_material --keyName=aes-name --keyNamespace=aes-namespace Crypto materials generated! -✨ Done in 1.86s. +✨ Done in 2.06s. + ``` + + diff --git a/src/plugins/credential_management/config.ts b/src/plugins/credential_management/config.ts index 506c04ebe422..1c2ce4920d6c 100644 --- a/src/plugins/credential_management/config.ts +++ b/src/plugins/credential_management/config.ts @@ -14,7 +14,7 @@ import { schema, TypeOf } from '@osd/config-schema'; export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: false }), materialPath: schema.string({ - defaultValue: 'src/plugins/credential_management/server/crypto/crypto_material', + defaultValue: 'data/crypto_material', }), }); diff --git a/src/plugins/credential_management/server/config_manager/config_manager.ts b/src/plugins/credential_management/server/config_manager/config_manager.ts deleted file mode 100644 index b271b02510f6..000000000000 --- a/src/plugins/credential_management/server/config_manager/config_manager.ts +++ /dev/null @@ -1,43 +0,0 @@ -// /* -// * SPDX-License-Identifier: Apache-2.0 -// * -// * The OpenSearch Contributors require contributions made to -// * this file be licensed under the Apache-2.0 license or a -// * compatible open source license. -// * -// * Any modifications Copyright OpenSearch Contributors. See -// * GitHub history for details. -// */ - -// import { PluginInitializerContext } from 'opensearch-dashboards/server'; -// import { TypeOf } from '@osd/config-schema'; -// import { configSchema } from '../../config'; - -// export class ConfigManager { -// private opensearchShardTimeout: number = 0; -// private graphiteAllowedUrls: string[] = []; -// private graphiteBlockedIPs: string[] = []; - -// constructor(config: PluginInitializerContext['config']) { -// config.create>().subscribe((configUpdate) => { -// this.graphiteAllowedUrls = configUpdate.graphiteAllowedUrls || []; -// this.graphiteBlockedIPs = configUpdate.graphiteBlockedIPs || []; -// }); - -// config.legacy.globalConfig$.subscribe((configUpdate) => { -// this.opensearchShardTimeout = configUpdate.opensearch.shardTimeout.asMilliseconds(); -// }); -// } - -// getOpenSearchShardTimeout() { -// return this.opensearchShardTimeout; -// } - -// getGraphiteAllowedUrls() { -// return this.graphiteAllowedUrls; -// } - -// getGraphiteBlockedIPs() { -// return this.graphiteBlockedIPs; -// } -// } diff --git a/src/plugins/credential_management/server/config_manager/index.ts b/src/plugins/credential_management/server/config_manager/index.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/plugins/credential_management/server/crypto/cli.ts b/src/plugins/credential_management/server/crypto/cli.ts index 81c04208a6d4..e2a7e00a65ad 100644 --- a/src/plugins/credential_management/server/crypto/cli.ts +++ b/src/plugins/credential_management/server/crypto/cli.ts @@ -17,9 +17,9 @@ import { } from '@aws-crypto/client-node'; import { randomBytes } from 'crypto'; -import { readFileSync, writeFile } from 'fs'; +import { readFileSync, writeFileSync } from 'fs'; -const defaultPath = "src/plugins/credential_management/server/crypto/crypto_material"; +const defaultPath = 'data/crypto_material'; export class CryptoCli { private static _instance: CryptoCli; @@ -31,13 +31,18 @@ export class CryptoCli { private constructor(path: string) { const wrappingSuite = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING; - // TODO: Move config to opensearch_dashboards.yam and load config during bootstrap - // TODO: Generate materials by default during bootstrap - // TODO: Add path validation with default calling generateCryptoMaterials - const cryptoMaterials = JSON.parse( - readFileSync(path, 'utf8') - ); + let cryptoMaterials; + try { + cryptoMaterials = JSON.parse(readFileSync(path, 'utf8')); + } catch (err) { + // Handle a file-not-found error + if (err.code === 'ENOENT') { + cryptoMaterials = JSON.parse(generateCryptoMaterials(path)); + } else { + throw err; + } + } const input = { keyName: cryptoMaterials.keyName, @@ -64,8 +69,7 @@ export class CryptoCli { return result.plaintext.toString(); } - // TODO: Append CryptoCli.getInstance into plugin lifecycle - public static getInstance(path=defaultPath): CryptoCli { + public static getInstance(path = defaultPath): CryptoCli { if (!CryptoCli._instance) { CryptoCli._instance = new CryptoCli(path); } @@ -74,17 +78,21 @@ export class CryptoCli { } } -const generateCryptoMaterials = function (keyName: string, keyNamespace: string, path=defaultPath) { +const generateCryptoMaterials = function ( + path = defaultPath, + keyName = 'keyName', + keyNamespace = 'keyNamespace' +) { const cryptoMaterials = { keyName, keyNamespace, unencryptedMasterKey: randomBytes(32), }; - - writeFile(path, JSON.stringify(cryptoMaterials), function (err) { - if (err) throw err; - }); + const input = JSON.stringify(cryptoMaterials); + writeFileSync(path, input); console.log('Crypto materials generated!'); + + return input; }; export { generateCryptoMaterials }; diff --git a/src/plugins/credential_management/server/index.ts b/src/plugins/credential_management/server/index.ts index 27cd08b79f8b..308b321ba27a 100644 --- a/src/plugins/credential_management/server/index.ts +++ b/src/plugins/credential_management/server/index.ts @@ -9,11 +9,16 @@ * GitHub history for details. */ +import { PluginConfigDescriptor } from 'opensearch-dashboards/server'; + import { PluginInitializerContext } from '../../../core/server'; import { CredentialManagementPlugin } from './plugin'; +import { configSchema, ConfigSchema } from '../config'; -// This exports static code and TypeScript types, -// as well as, OpenSearch Dashboards Platform `plugin()` initializer. +// TODO: Add exposeToBrowser for conditional rendering +export const config: PluginConfigDescriptor = { + schema: configSchema, +}; export function plugin(initializerContext: PluginInitializerContext) { return new CredentialManagementPlugin(initializerContext); diff --git a/src/plugins/credential_management/server/plugin.ts b/src/plugins/credential_management/server/plugin.ts index 163972ff9dba..05293adad144 100644 --- a/src/plugins/credential_management/server/plugin.ts +++ b/src/plugins/credential_management/server/plugin.ts @@ -25,8 +25,7 @@ import { ConfigSchema } from '../config'; import { CryptoCli } from './crypto'; export class CredentialManagementPlugin - implements Plugin -{ + implements Plugin { private readonly logger: Logger; private initializerContext: PluginInitializerContext; @@ -39,17 +38,20 @@ export class CredentialManagementPlugin public async setup(core: CoreSetup) { this.logger.debug('credential_management: Setup'); - const router = core.http.createRouter(); - - // Register server side APIs - registerRoutes(router); - - // Register credential saved object type - core.savedObjects.registerType(credentialSavedObjectType); - - const config = await this.initializerContext.config.create().pipe(first()).toPromise(); - this.logger.debug('Config: ' + config.enabled); - + const { enabled, materialPath } = await this.initializerContext.config + .create() + .pipe(first()) + .toPromise(); + + if (enabled) { + const router = core.http.createRouter(); + // Register server side APIs + registerRoutes(router); + // Register credential saved object type + core.savedObjects.registerType(credentialSavedObjectType); + // Instantiate CryptoCli for encryption / decryption + this.cryptoCli = CryptoCli.getInstance(materialPath); + } return {}; } From 8b4e984bd97bc48a1af935ad5289cccb22da19b1 Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Thu, 21 Jul 2022 23:30:02 -0700 Subject: [PATCH 5/7] Resolve comments --- config/opensearch_dashboards.yml | 6 +----- .../credential_management/server/plugin.ts | 19 +++++++++---------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml index 44d203726005..52e72e252e7f 100644 --- a/config/opensearch_dashboards.yml +++ b/config/opensearch_dashboards.yml @@ -184,9 +184,5 @@ # for reducing the load of OpenSearch cluster. # data.search.usageTelemetry.enabled: false -# Set the value of this setting to true to enable credential management for managing -# the credentials of OpenSearch cluster. -# It's enabled now for for playground env CD -# TODO: Disable it for release -credential_management.enabled: true +# Set the value of this setting to custermize config # credential_management.materialPath: "path/to/your/crypto_material" diff --git a/src/plugins/credential_management/server/plugin.ts b/src/plugins/credential_management/server/plugin.ts index 05293adad144..225b0dea03a8 100644 --- a/src/plugins/credential_management/server/plugin.ts +++ b/src/plugins/credential_management/server/plugin.ts @@ -38,20 +38,19 @@ export class CredentialManagementPlugin public async setup(core: CoreSetup) { this.logger.debug('credential_management: Setup'); - const { enabled, materialPath } = await this.initializerContext.config + const { materialPath } = await this.initializerContext.config .create() .pipe(first()) .toPromise(); - if (enabled) { - const router = core.http.createRouter(); - // Register server side APIs - registerRoutes(router); - // Register credential saved object type - core.savedObjects.registerType(credentialSavedObjectType); - // Instantiate CryptoCli for encryption / decryption - this.cryptoCli = CryptoCli.getInstance(materialPath); - } + const router = core.http.createRouter(); + // Register server side APIs + registerRoutes(router); + // Register credential saved object type + core.savedObjects.registerType(credentialSavedObjectType); + // Instantiate CryptoCli for encryption / decryption + this.cryptoCli = CryptoCli.getInstance(materialPath); + return {}; } From dd9d7505d6d2dbace49663304eeaffbb407f5d5e Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Fri, 22 Jul 2022 00:23:42 -0700 Subject: [PATCH 6/7] Add multipleDataSource global config --- config/opensearch_dashboards.yml | 7 +++++- .../server/opensearch_dashboards_config.ts | 3 +++ src/core/server/plugins/types.ts | 7 +++++- src/legacy/server/config/schema.js | 3 +++ src/plugins/credential_management/README.md | 2 +- src/plugins/credential_management/config.ts | 1 - .../credential_management/server/plugin.ts | 24 ++++++++++++------- 7 files changed, 34 insertions(+), 13 deletions(-) diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml index 52e72e252e7f..068d3ece2fbe 100644 --- a/config/opensearch_dashboards.yml +++ b/config/opensearch_dashboards.yml @@ -184,5 +184,10 @@ # for reducing the load of OpenSearch cluster. # data.search.usageTelemetry.enabled: false -# Set the value of this setting to custermize config +# Set the value of this setting to true to enable all multipleDataSource +# related features including: +# 1. credential management for managing the credential of each OpenSearch cluster. +# 2. data source management for managing the connection endpoint of each OpenSearch cluster. +# opensearchDashboards.multipleDataSource.enabled: false +# Set the value of this setting to custermize config # credential_management.materialPath: "path/to/your/crypto_material" diff --git a/src/core/server/opensearch_dashboards_config.ts b/src/core/server/opensearch_dashboards_config.ts index ad88e8a89cad..f005cfb724f3 100644 --- a/src/core/server/opensearch_dashboards_config.ts +++ b/src/core/server/opensearch_dashboards_config.ts @@ -82,6 +82,9 @@ export const config = { defaultValue: '', }), }), + multipleDataSource: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), }), deprecations, }; diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index cf769b45daa3..541bfb33339e 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -272,7 +272,12 @@ export interface Plugin< export const SharedGlobalConfigKeys = { // We can add more if really needed - opensearchDashboards: ['index', 'autocompleteTerminateAfter', 'autocompleteTimeout'] as const, + opensearchDashboards: [ + 'index', + 'autocompleteTerminateAfter', + 'autocompleteTimeout', + 'multipleDataSource', + ] as const, opensearch: ['shardTimeout', 'requestTimeout', 'pingTimeout'] as const, path: ['data'] as const, savedObjects: ['maxImportPayloadBytes'] as const, diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index d1d1a9337f05..323d327bf2fd 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -246,6 +246,9 @@ export default () => faviconUrl: Joi.any().default('/'), applicationTitle: Joi.any().default(''), }), + multipleDataSource: Joi.object({ + enabled: Joi.boolean().default(true), + }), }).default(), savedObjects: HANDLED_IN_NEW_PLATFORM, diff --git a/src/plugins/credential_management/README.md b/src/plugins/credential_management/README.md index 4287b40db7d4..44770e5c075a 100755 --- a/src/plugins/credential_management/README.md +++ b/src/plugins/credential_management/README.md @@ -15,7 +15,7 @@ setting up your development environment. 1. To enable this feature, override config/opensearch_dashboards.yml ``` -credential_management.enabled: true +opensearchDashboards.multipleDataSource.enabled: true ``` 2. To setup path for crypto material, override config/opensearch_dashboards.yml diff --git a/src/plugins/credential_management/config.ts b/src/plugins/credential_management/config.ts index 1c2ce4920d6c..38e5e7637dfa 100644 --- a/src/plugins/credential_management/config.ts +++ b/src/plugins/credential_management/config.ts @@ -12,7 +12,6 @@ import { schema, TypeOf } from '@osd/config-schema'; export const configSchema = schema.object({ - enabled: schema.boolean({ defaultValue: false }), materialPath: schema.string({ defaultValue: 'data/crypto_material', }), diff --git a/src/plugins/credential_management/server/plugin.ts b/src/plugins/credential_management/server/plugin.ts index 225b0dea03a8..9f19f464f06e 100644 --- a/src/plugins/credential_management/server/plugin.ts +++ b/src/plugins/credential_management/server/plugin.ts @@ -38,19 +38,25 @@ export class CredentialManagementPlugin public async setup(core: CoreSetup) { this.logger.debug('credential_management: Setup'); - const { materialPath } = await this.initializerContext.config - .create() + + const { opensearchDashboards } = await this.initializerContext.config.legacy.globalConfig$ .pipe(first()) .toPromise(); - const router = core.http.createRouter(); - // Register server side APIs - registerRoutes(router); - // Register credential saved object type - core.savedObjects.registerType(credentialSavedObjectType); - // Instantiate CryptoCli for encryption / decryption - this.cryptoCli = CryptoCli.getInstance(materialPath); + if (opensearchDashboards.multipleDataSource.enabled) { + const { materialPath } = await this.initializerContext.config + .create() + .pipe(first()) + .toPromise(); + const router = core.http.createRouter(); + // Register server side APIs + registerRoutes(router); + // Register credential saved object type + core.savedObjects.registerType(credentialSavedObjectType); + // Instantiate CryptoCli for encryption / decryption + this.cryptoCli = CryptoCli.getInstance(materialPath); + } return {}; } From 7b5a031c14e243c24b4c355f5f3e1996667e01f0 Mon Sep 17 00:00:00 2001 From: Louis Chu Date: Fri, 22 Jul 2022 14:10:38 -0700 Subject: [PATCH 7/7] Fix merge issues --- scripts/crypto_materials_generator.js | 4 +-- .../client/data_source_client.ts | 2 +- .../server/crypto/cli.ts | 34 ------------------- .../server/crypto/crypto_cli.ts | 12 +++++++ .../server/crypto/index.ts | 4 +-- .../{ => singleton}/cryptography_singleton.ts | 22 ++++++++++-- .../server/crypto/singleton/index.ts | 12 +++++++ .../credential_management/server/index.ts | 1 + .../credential_management/server/plugin.ts | 10 ++++-- 9 files changed, 56 insertions(+), 45 deletions(-) delete mode 100644 src/plugins/credential_management/server/crypto/cli.ts create mode 100644 src/plugins/credential_management/server/crypto/crypto_cli.ts rename src/plugins/credential_management/server/crypto/{ => singleton}/cryptography_singleton.ts (82%) create mode 100644 src/plugins/credential_management/server/crypto/singleton/index.ts diff --git a/scripts/crypto_materials_generator.js b/scripts/crypto_materials_generator.js index b94a312d98f1..bc4cd13e437f 100644 --- a/scripts/crypto_materials_generator.js +++ b/scripts/crypto_materials_generator.js @@ -12,6 +12,6 @@ require('../src/setup_node_env'); var args = require('yargs').argv; -var { generateCryptoMaterials } = require('../src/plugins/credential_management/server/crypto'); +var generateCryptoMaterials = require('../src/plugins/credential_management/server/crypto/crypto_cli'); -generateCryptoMaterials(args.keyName, args.keyNamespace); +generateCryptoMaterials(args.path, args.keyName, args.keyNamespace); diff --git a/src/core/server/opensearch_data/client/data_source_client.ts b/src/core/server/opensearch_data/client/data_source_client.ts index 058213a27605..67e975d67058 100644 --- a/src/core/server/opensearch_data/client/data_source_client.ts +++ b/src/core/server/opensearch_data/client/data_source_client.ts @@ -11,7 +11,7 @@ import { Logger } from '../../logging'; import { OpenSearchClient, OpenSearchClientConfig } from '../../opensearch/client'; import { SavedObjectsClientContract } from '../../saved_objects/types'; // @ts-ignore -import { CryptographySingleton } from '../../../../../src/plugins/credential_management/server/crypto'; +import { CryptographySingleton } from '../../../../../src/plugins/credential_management/server/crypto/singleton/cryptography_singleton'; /** * TODO: update doc diff --git a/src/plugins/credential_management/server/crypto/cli.ts b/src/plugins/credential_management/server/crypto/cli.ts deleted file mode 100644 index 90cae7c6dd1a..000000000000 --- a/src/plugins/credential_management/server/crypto/cli.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -import { randomBytes } from 'crypto'; -import { writeFileSync } from 'fs'; - -const defaultPath = 'data/crypto_material'; - -const generateCryptoMaterials = function ( - path = defaultPath, - keyName = 'keyName', - keyNamespace = 'keyNamespace' -) { - const cryptoMaterials = { - keyName, - keyNamespace, - unencryptedMasterKey: randomBytes(32), - }; - const input = JSON.stringify(cryptoMaterials); - writeFileSync(path, input); - console.log('Crypto materials generated!'); - - return input; -}; - -export { generateCryptoMaterials }; diff --git a/src/plugins/credential_management/server/crypto/crypto_cli.ts b/src/plugins/credential_management/server/crypto/crypto_cli.ts new file mode 100644 index 000000000000..424d23da46a9 --- /dev/null +++ b/src/plugins/credential_management/server/crypto/crypto_cli.ts @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +export { generateCryptoMaterials } from './singleton'; diff --git a/src/plugins/credential_management/server/crypto/index.ts b/src/plugins/credential_management/server/crypto/index.ts index 42d443e1600c..53887413c459 100644 --- a/src/plugins/credential_management/server/crypto/index.ts +++ b/src/plugins/credential_management/server/crypto/index.ts @@ -9,5 +9,5 @@ * GitHub history for details. */ -export { CryptographySingleton } from './cryptography_singleton'; -export { generateCryptoMaterials } from './cli'; +export { CryptographySingleton } from './singleton/cryptography_singleton'; +export { generateCryptoMaterials } from './crypto_cli'; diff --git a/src/plugins/credential_management/server/crypto/cryptography_singleton.ts b/src/plugins/credential_management/server/crypto/singleton/cryptography_singleton.ts similarity index 82% rename from src/plugins/credential_management/server/crypto/cryptography_singleton.ts rename to src/plugins/credential_management/server/crypto/singleton/cryptography_singleton.ts index 247715e1b427..1889315c77ac 100644 --- a/src/plugins/credential_management/server/crypto/cryptography_singleton.ts +++ b/src/plugins/credential_management/server/crypto/singleton/cryptography_singleton.ts @@ -16,9 +16,8 @@ import { RawAesWrappingSuiteIdentifier, } from '@aws-crypto/client-node'; -import { readFileSync } from 'fs'; - -import { generateCryptoMaterials } from './cli'; +import { randomBytes } from 'crypto'; +import { readFileSync, writeFileSync } from 'fs'; const defaultPath = 'data/crypto_material'; @@ -82,3 +81,20 @@ export class CryptographySingleton { return CryptographySingleton._instance; } } + +export const generateCryptoMaterials = function ( + path = defaultPath, + keyName = 'keyName', + keyNamespace = 'keyNamespace' +) { + const cryptoMaterials = { + keyName, + keyNamespace, + unencryptedMasterKey: randomBytes(32), + }; + const input = JSON.stringify(cryptoMaterials); + writeFileSync(path, input); + console.log('Crypto materials generated!'); + + return input; +}; diff --git a/src/plugins/credential_management/server/crypto/singleton/index.ts b/src/plugins/credential_management/server/crypto/singleton/index.ts new file mode 100644 index 000000000000..c9ee477dc4e2 --- /dev/null +++ b/src/plugins/credential_management/server/crypto/singleton/index.ts @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +export { CryptographySingleton, generateCryptoMaterials } from './cryptography_singleton'; diff --git a/src/plugins/credential_management/server/index.ts b/src/plugins/credential_management/server/index.ts index 308b321ba27a..6d47d5221764 100644 --- a/src/plugins/credential_management/server/index.ts +++ b/src/plugins/credential_management/server/index.ts @@ -25,3 +25,4 @@ export function plugin(initializerContext: PluginInitializerContext) { } export { CredentialManagementPluginSetup, CredentialManagementPluginStart } from './types'; +export { CryptographySingleton, generateCryptoMaterials } from './crypto'; diff --git a/src/plugins/credential_management/server/plugin.ts b/src/plugins/credential_management/server/plugin.ts index 823ab24b8f3a..2abdba17dc68 100644 --- a/src/plugins/credential_management/server/plugin.ts +++ b/src/plugins/credential_management/server/plugin.ts @@ -22,14 +22,14 @@ import { CredentialManagementPluginSetup, CredentialManagementPluginStart } from import { registerRoutes } from './routes'; import { credentialSavedObjectType } from './saved_objects'; import { ConfigSchema } from '../config'; -import { CryptoCli } from './crypto'; +import { CryptographySingleton } from './crypto'; export class CredentialManagementPlugin implements Plugin { private readonly logger: Logger; private initializerContext: PluginInitializerContext; - private cryptoCli?: CryptoCli; + private cryptographySingleton?: CryptographySingleton; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); @@ -56,7 +56,11 @@ export class CredentialManagementPlugin // Register credential saved object type core.savedObjects.registerType(credentialSavedObjectType); // Instantiate CryptoCli for encryption / decryption - this.cryptoCli = CryptoCli.getInstance(materialPath, keyName, keyNamespace); + this.cryptographySingleton = CryptographySingleton.getInstance( + materialPath, + keyName, + keyNamespace + ); } return {}; }