diff --git a/CHANGELOG.md b/CHANGELOG.md index 1353beef3d6f..3d639a41ad90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [BUG] Add platform "darwin-arm64" to unit test ([#5290](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5290)) - [BUG][Dev Tool] Add dev tool documentation link to dev tool's help menu [#5166](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5166) - Fix missing border for header navigation control on right ([#5450](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5450)) +- [BUG] Fix filtering issue in data source selector ([5484](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5484)) +- [BUG][Data] Support for custom filters with heterogeneous data fields ([5577](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5577)) ### 🚞 Infrastructure @@ -40,6 +42,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Add an achievement badger to the PR ([#3721](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3721)) - [CI] Enable inputs for manually triggered Cypress test jobs ([#5134](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5134)) - [CI] Replace usage of deprecated `set-output` in workflows ([#5340](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5340)) +- [Chore] Add `--security` for `opensearch snapshot` and `opensearch_dashboards` to configure local setup with the security plugin ([#5451](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5451)) ### 📝 Documentation diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 748210537e63..2beb18edc526 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -252,10 +252,11 @@ Options: -E Additional key=value settings to pass to OpenSearch --download-only Download the snapshot but don't actually start it --ssl Sets up SSL on OpenSearch + --security Installs and sets up OpenSearch Security plugin on the cluster --P OpenSearch plugin artifact URL to install it on the cluster. ```bash -$ yarn opensearch snapshot --version 2.2.0 -E cluster.name=test -E path.data=/tmp/opensearch-data --P org.opensearch.plugin:test-plugin:2.2.0.0 --P file:/home/user/opensearch-test-plugin-2.2.0.0.zip +$ yarn opensearch snapshot --version 2.2.0 -E cluster.name=test -E path.data=/tmp/opensearch-data --P org.opensearch.plugin:test-plugin:2.2.0.0 --P file:/home/user/opensearch-test-plugin-2.2.0.0.zip --security ``` #### Read Only capabilities @@ -281,6 +282,18 @@ This method can also be used to develop against the [full distribution of OpenSe _This step is only mandatory if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled._ +> 1. Run `export initialAdminPassword=` since it's needed by the configuration script +> 2. Run `yarn opensearch snapshot --security` +> 3. Wait a few seconds while the plugin is installed, configured, and OpenSearch starts up. + +Then within another window. You can start: + +> 1. Run `export OPENSEARCH_USERNAME=admin` +> 2. Run `export OPENSEARCH_PASSWORD=` +> 3. Optional: Run `export OPENSEARCH_SECURITY_READONLY_ROLE=` +> 4. Run `yarn start:security` +> 5. Navigate to OpenSearch Dashboards and login with the above username and password. + Once the bootstrap of OpenSearch Dashboards is finished, you need to apply some changes to the default [`opensearch_dashboards.yml`](https://github.com/opensearch-project/OpenSearch-Dashboards/blob/main/config/opensearch_dashboards.yml#L25-L72) in order to connect to OpenSearch. diff --git a/README.md b/README.md index 5bafaf4c7c1a..e8e2da025df7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ We aim to be an exceptional community-driven platform and to foster open partici You can [contribute to this project](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/CONTRIBUTING.md) by [opening issues](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/new/choose) to give feedback, share ideas, identify bugs, and contribute code. -Set up your [OpenSearch Dashboards development environment](ttps://github.com/opensearch-project/OpenSearch-Dashboards/blob/main/DEVELOPER_GUIDE.md#getting-started-guide) today! The project team looks forward to your contributions. +Set up your [OpenSearch Dashboards development environment](https://github.com/opensearch-project/OpenSearch-Dashboards/blob/main/DEVELOPER_GUIDE.md#getting-started-guide) today! The project team looks forward to your contributions. ## Code Summary diff --git a/package.json b/package.json index b95306a049e7..46bbeae88849 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "build": "scripts/use_node scripts/build --all-platforms", "start": "scripts/use_node scripts/opensearch_dashboards --dev", "start:docker": "scripts/use_node scripts/opensearch_dashboards --dev --opensearch.hosts=$OPENSEARCH_HOSTS --opensearch.ignoreVersionMismatch=true --server.host=$SERVER_HOST", + "start:security": "scripts/use_node scripts/opensearch_dashboards --dev --security", "debug": "scripts/use_node --nolazy --inspect scripts/opensearch_dashboards --dev", "debug-break": "scripts/use_node --nolazy --inspect-brk scripts/opensearch_dashboards --dev", "lint": "yarn run lint:es && yarn run lint:style", diff --git a/packages/osd-opensearch/src/cli_commands/snapshot.js b/packages/osd-opensearch/src/cli_commands/snapshot.js index 3cf8701856bd..ff21dbe851c8 100644 --- a/packages/osd-opensearch/src/cli_commands/snapshot.js +++ b/packages/osd-opensearch/src/cli_commands/snapshot.js @@ -49,6 +49,7 @@ exports.help = (defaults = {}) => { -E Additional key=value settings to pass to OpenSearch --download-only Download the snapshot but don't actually start it --ssl Sets up SSL on OpenSearch + --security Installs and sets up the OpenSearch Security plugin on the cluster --P OpenSearch plugin artifact URL to install it on the cluster. We can use the flag multiple times to install multiple plugins on the cluster snapshot. The argument value can be url to zip file, maven coordinates of the plugin or for local zip files, use file:. @@ -74,6 +75,8 @@ exports.run = async (defaults = {}) => { boolean: ['download-only'], + boolean: ['security'], + default: defaults, }); @@ -91,6 +94,10 @@ exports.run = async (defaults = {}) => { await cluster.installOpenSearchPlugins(installPath, options.opensearchPlugins); } + if (options.security) { + await cluster.setupSecurity(installPath, options.version ?? defaults.version); + } + options.bundledJDK = true; await cluster.run(installPath, options); diff --git a/packages/osd-opensearch/src/cluster.js b/packages/osd-opensearch/src/cluster.js index 3527668eed05..455a1e5f919f 100644 --- a/packages/osd-opensearch/src/cluster.js +++ b/packages/osd-opensearch/src/cluster.js @@ -34,7 +34,7 @@ const execa = require('execa'); const chalk = require('chalk'); const path = require('path'); const { downloadSnapshot, installSnapshot, installSource, installArchive } = require('./install'); -const { OPENSEARCH_BIN, OPENSEARCH_PLUGIN } = require('./paths'); +const { OPENSEARCH_BIN, OPENSEARCH_PLUGIN, OPENSEARCH_SECURITY_INSTALL } = require('./paths'); const { log: defaultLog, parseOpenSearchLog, extractConfigFiles, decompress } = require('./utils'); const { createCliError } = require('./errors'); const { promisify } = require('util'); @@ -42,6 +42,19 @@ const treeKillAsync = promisify(require('tree-kill')); const { parseSettings, SettingsFilter } = require('./settings'); const { CA_CERT_PATH, OPENSEARCH_P12_PATH, OPENSEARCH_P12_PASSWORD } = require('@osd/dev-utils'); const readFile = util.promisify(fs.readFile); +const chmodAsync = util.promisify(fs.chmod); + +const LATEST_ENGINE_PLUGIN_BASE_URL = + 'https://ci.opensearch.org/ci/dbc/distribution-build-opensearch'; + +function generateEnginePluginUrl(version, plugin) { + const legacyVersion = `${version}.0`; + const [platform, type] = + process.platform === 'win32' ? ['windows', 'zip'] : [process.platform, 'tar']; + const arch = process.arch === 'arm64' ? 'arm64' : 'x64'; + + return `${LATEST_ENGINE_PLUGIN_BASE_URL}/${version}/latest/${platform}/${arch}/${type}/builds/opensearch/plugins/${plugin}-${legacyVersion}.zip`; +} // listen to data on stream until map returns anything but undefined const first = (stream, map) => @@ -57,9 +70,10 @@ const first = (stream, map) => }); exports.Cluster = class Cluster { - constructor({ log = defaultLog, ssl = false } = {}) { + constructor({ log = defaultLog, ssl = false, security = false } = {}) { this._log = log; this._ssl = ssl; + this._security = security; this._caCertPromise = ssl ? readFile(CA_CERT_PATH) : undefined; } @@ -193,6 +207,23 @@ exports.Cluster = class Cluster { } } + /** + * Setups cluster with security demo configuration + * + * @param {string} installPath + * @property {String} version - version of OpenSearch + */ + async setupSecurity(installPath, version) { + const pluginUrl = generateEnginePluginUrl(version, 'opensearch-security'); + await this.installOpenSearchPlugins(installPath, pluginUrl); + this._log.info('Setting up security'); + const pluginPath = path.resolve(installPath, OPENSEARCH_SECURITY_INSTALL); + if (pluginPath) { + await chmodAsync(pluginPath, '755'); + await execa(OPENSEARCH_SECURITY_INSTALL, ['-y', '-i', '-s'], { cwd: installPath }); + } + } + /** * Starts OpenSearch and returns resolved promise once started * diff --git a/packages/osd-opensearch/src/paths.js b/packages/osd-opensearch/src/paths.js index 93bb80e97ff1..d316f7cd41bf 100644 --- a/packages/osd-opensearch/src/paths.js +++ b/packages/osd-opensearch/src/paths.js @@ -35,6 +35,10 @@ function maybeUseBat(bin) { return os.platform().startsWith('win') ? `${bin}.bat` : bin; } +function maybeUseBatOrShell(bin) { + return os.platform().startsWith('win') ? `${bin}.bat` : `${bin}.sh`; +} + const tempDir = os.tmpdir(); exports.BASE_PATH = path.resolve(tempDir, 'osd-opensearch'); @@ -45,3 +49,6 @@ exports.OPENSEARCH_CONFIG = 'config/opensearch.yml'; exports.OPENSEARCH_KEYSTORE_BIN = maybeUseBat('./bin/opensearch-keystore'); exports.OPENSEARCH_PLUGIN = maybeUseBat('./bin/opensearch-plugin'); +exports.OPENSEARCH_SECURITY_INSTALL = maybeUseBatOrShell( + './plugins/opensearch-security/tools/install_demo_configuration' +); diff --git a/release-notes/opensearch-dashboards.release-notes-1.3.14.md b/release-notes/opensearch-dashboards.release-notes-1.3.14.md new file mode 100644 index 000000000000..441b7a602257 --- /dev/null +++ b/release-notes/opensearch-dashboards.release-notes-1.3.14.md @@ -0,0 +1,19 @@ +# Version 1.3.14 Release Notes + +### 🛡 Security + +- [CVE-2023-46234] Bump `eslint-import-resolver-webpack` from `0.11.1` to `0.13.8` and `browserify-sign` from `4.2.1` to `4.2.2` ([#5414](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5414/)) +- [CVE-2023-45133] Add package resolution for `@babel/traverse` to `7.23.2` to fix vulnerability ([#5309](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5309)) +- [CVE-2017-16137] Bump `debug` versions via yarn updates and resolutions ([#5573](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5573)) + +### 📈 Features/Enhancements + +### 🐛 Bug Fixes + +### 🚞 Infrastructure + +### 📝 Documentation + +### 🛠 Maintenance + +- [Version] Increment version to 1.3.14 ([#5531](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5531)) diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 6f89911ed089..28dea22f4a0b 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -125,6 +125,60 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) { set('opensearch.hosts', opensearchHosts); set('opensearch.ssl.certificateAuthorities', CA_CERT_PATH); } + + if (opts.security) { + const customOpenSearchHosts = opts.opensearch + ? opts.opensearch.split(',') + : [].concat(get('opensearch.hosts') || []); + + const opensearchHosts = ( + (customOpenSearchHosts.length > 0 && customOpenSearchHosts) || ['https://localhost:9200'] + ).map((hostUrl) => { + const parsedUrl = new URL('', hostUrl); + return `https://localhost:${parsedUrl.port}`; + }); + + if (!get('opensearch.hosts')) { + set('opensearch.hosts', opensearchHosts); + } + + if (!get('opensearch.ssl.verificationMode')) { + set('opensearch.ssl.verificationMode', 'none'); + } + + if (get('opensearch.username') === 'opensearch_dashboards_system') { + set('opensearch.username', process.env.OPENSEARCH_USERNAME); + } + + if (get('opensearch.password') === 'changeme') { + set('opensearch.password', process.env.OPENSEARCH_PASSWORD); + } + + if (!get('opensearch.requestHeadersWhitelist')) { + set('opensearch.requestHeadersWhitelist', ['authorization', 'securitytenant']); + } + + if (!get('opensearch_security.multitenancy.enabled')) { + set('opensearch_security.multitenancy.enabled', true); + } + + if (!get('opensearch_security.multitenancy.tenants.preferred')) { + set('opensearch_security.multitenancy.tenants.preferred', ['Private', 'Global']); + } + + if ( + !get('opensearch_security.readonly_mode.roles') && + process.env.OPENSEARCH_SECURITY_READONLY_ROLE + ) { + set('opensearch_security.readonly_mode.roles', [ + process.env.OPENSEARCH_SECURITY_READONLY_ROLE, + ]); + } + + if (!get('opensearch_security.cookie.secure')) { + set('opensearch_security.cookie.secure', false); + } + } } if (opts.opensearch) set('opensearch.hosts', opts.opensearch.split(',')); @@ -195,6 +249,7 @@ export default function (program) { command .option('--dev', 'Run the server with development mode defaults') .option('--ssl', 'Run the dev server using HTTPS') + .option('--security', 'Run the dev server using security defaults') .option('--dist', 'Use production assets from osd/optimizer') .option( '--no-base-path', diff --git a/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.test.ts b/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.test.ts index f610b1e7179f..ad68e14b2c54 100644 --- a/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.test.ts +++ b/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.test.ts @@ -66,4 +66,18 @@ describe('filterMatchesIndex', () => { expect(filterMatchesIndex(filter, indexPattern)).toBe(true); }); + + it('should return false if the custom filter is a different index id', () => { + const filter = { meta: { index: 'foo', key: 'bar', type: 'custom' } } as Filter; + const indexPattern = { id: 'bar', fields: [{ name: 'foo' }] } as IIndexPattern; + + expect(filterMatchesIndex(filter, indexPattern)).toBe(false); + }); + + it('should return true if the custom filter is the same index id', () => { + const filter = { meta: { index: 'foo', key: 'bar', type: 'custom' } } as Filter; + const indexPattern = { id: 'foo', fields: [{ name: 'barf' }] } as IIndexPattern; + + expect(filterMatchesIndex(filter, indexPattern)).toBe(true); + }); }); diff --git a/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.ts b/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.ts index f8c2ab67ee95..529e68609aeb 100644 --- a/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.ts +++ b/src/plugins/data/common/opensearch_query/opensearch_query/filter_matches_index.ts @@ -31,14 +31,14 @@ import { IIndexPattern, IFieldType } from '../../index_patterns'; import { Filter } from '../filters'; -/* - * TODO: We should base this on something better than `filter.meta.key`. We should probably modify - * this to check if `filter.meta.index` matches `indexPattern.id` instead, but that's a breaking - * change. - */ export function filterMatchesIndex(filter: Filter, indexPattern?: IIndexPattern | null) { if (!filter.meta?.key || !indexPattern) { return true; } + + if (filter.meta?.type === 'custom') { + return filter.meta.index === indexPattern.id; + } + return indexPattern.fields.some((field: IFieldType) => field.name === filter.meta.key); } diff --git a/src/plugins/data/public/data_sources/datasource_selector/datasource_selectable.tsx b/src/plugins/data/public/data_sources/datasource_selector/datasource_selectable.tsx index f522da79c129..aaab4d57c830 100644 --- a/src/plugins/data/public/data_sources/datasource_selector/datasource_selectable.tsx +++ b/src/plugins/data/public/data_sources/datasource_selector/datasource_selectable.tsx @@ -129,7 +129,6 @@ export const DataSourceSelectable = ({ onChange={handleSourceChange} singleSelection={singleSelection} isClearable={false} - async /> ); };