From d34bcdb018490572c0f61d1a76012384580690e1 Mon Sep 17 00:00:00 2001 From: Theo Truong Date: Mon, 29 Jan 2024 13:05:27 -0700 Subject: [PATCH 1/2] Update Default Password for OS 2.12 - Updated secured test suite to use strong password when OS 2.12 or up is detected - Removed autoheal - Simplified client creation step for the guides Signed-off-by: Theo Truong --- .ci/opensearch/Dockerfile.opensearch | 6 ---- .ci/opensearch/docker-compose.yml | 12 +------- .github/workflows/compatibility.yml | 5 ++-- .github/workflows/integration.yml | 9 +++++- CHANGELOG.md | 3 ++ USER_GUIDE.md | 2 +- guides/advanced_index_actions.md | 5 ++-- guides/index_lifecycle.md | 14 ++------- guides/json.md | 9 +----- guides/msearch.md | 12 +------- guides/search.md | 24 ++------------- lib/tools.d.ts | 11 +++++++ lib/tools.js | 21 +++++++++++++ test/integration/helper.js | 18 ++++++++++- test/integration/helpers-secure/http.test.js | 13 ++------ .../integration/helpers-secure/search.test.js | 14 ++------- .../helpers-secure/security.test.js | 13 ++------ test/unit/tools.test.js | 30 +++++++++++++++++++ 18 files changed, 110 insertions(+), 111 deletions(-) create mode 100644 lib/tools.d.ts create mode 100644 lib/tools.js create mode 100644 test/unit/tools.test.js diff --git a/.ci/opensearch/Dockerfile.opensearch b/.ci/opensearch/Dockerfile.opensearch index e248a6206..67a1a3b13 100644 --- a/.ci/opensearch/Dockerfile.opensearch +++ b/.ci/opensearch/Dockerfile.opensearch @@ -5,10 +5,4 @@ ARG opensearch_path=/usr/share/opensearch ARG opensearch_yml=$opensearch_path/config/opensearch.yml ARG SECURE_INTEGRATION - -HEALTHCHECK --start-period=20s --interval=5s --retries=2 --timeout=1s \ - CMD if [ "$SECURE_INTEGRATION" != "true" ]; \ - then curl --fail localhost:9200/_cat/health; \ - else curl --fail -k https:/localhost:9200/_cat/health -u admin:admin; fi - RUN if [ "$SECURE_INTEGRATION" != "true" ] ; then $opensearch_path/bin/opensearch-plugin remove opensearch-security; fi diff --git a/.ci/opensearch/docker-compose.yml b/.ci/opensearch/docker-compose.yml index 977dbb3b1..4bec512d2 100644 --- a/.ci/opensearch/docker-compose.yml +++ b/.ci/opensearch/docker-compose.yml @@ -12,17 +12,7 @@ services: environment: - discovery.type=single-node - bootstrap.memory_lock=true - - SECURE_INTEGRATION=${SECURE_INTEGRATION:-false} + - OPENSEARCH_INITIAL_ADMIN_PASSWORD=myStrongPassword123! ports: - '9200:9200' user: opensearch - autoheal: - restart: always - image: willfarrell/autoheal - environment: - - AUTOHEAL_CONTAINER_LABEL=all - - AUTOHEAL_START_PERIOD=30 - - AUTOHEAL_INTERVAL=5 - - AUTOHEAL_DEFAULT_STOP_TIMEOUT=30 - volumes: - - /var/run/docker.sock:/var/run/docker.sock diff --git a/.github/workflows/compatibility.yml b/.github/workflows/compatibility.yml index b711236a2..8a86df0e9 100644 --- a/.github/workflows/compatibility.yml +++ b/.github/workflows/compatibility.yml @@ -31,6 +31,9 @@ jobs: - { opensearch_version: 1.3.3 } - { opensearch_version: 2.0.0 } - { opensearch_version: 2.0.1 } + env: + OPENSEARCH_VERSION: ${{ matrix.entry.opensearch_version }} + SECURE_INTEGRATION: ${{ matrix.secured }} steps: - uses: actions/checkout@v2 @@ -45,8 +48,6 @@ jobs: - name: Runs OpenSearch cluster id: start_opensearch_cluster run: | - export OPENSEARCH_VERSION=${{ matrix.entry.opensearch_version }} - export SECURE_INTEGRATION=${{ matrix.secured }} make cluster.clean cluster.opensearch.build cluster.opensearch.start - name: Use Node.js 16.x diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index a99674a15..c2471433d 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -19,6 +19,10 @@ jobs: matrix: node-version: [10.x, 12.x, 14.x, 16.x, 18.x] + env: + OPENSEARCH_VERSION: latest + SECURE_INTEGRATION: false + steps: - uses: actions/checkout@v2 @@ -65,6 +69,10 @@ jobs: matrix: node-version: [10.x, 12.x, 14.x, 16.x, 18.x] + env: + OPENSEARCH_VERSION: latest + SECURE_INTEGRATION: true + steps: - uses: actions/checkout@v2 @@ -77,7 +85,6 @@ jobs: - name: Runs OpenSearch secure cluster run: | - export SECURE_INTEGRATION=true make cluster.clean cluster.opensearch.build cluster.opensearch.start - name: Use Node.js ${{ matrix.node-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1354047c3..f835531f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,11 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Bumps `eslint-plugin-prettier` from 5.1.2 to 5.1.3 - Bumps `@babel/eslint-parser` from 7.23.3 to 7.23.9 ### Changed +- Updated integration tests to use strong password in OS 2.12 and up ([#707](https://github.com/opensearch-project/opensearch-js/pull/707)) +- Simplified client creation in the guides ([#707](https://github.com/opensearch-project/opensearch-js/pull/707)) ### Deprecated ### Removed +- Removed AutoHeal([#707](https://github.com/opensearch-project/opensearch-js/pull/707)) ### Fixed ### Security diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 7af770049..8545cc8d8 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -26,7 +26,7 @@ var host = 'localhost'; var protocol = 'https'; var port = 9200; -var auth = 'admin:admin'; // For testing only. Don't store credentials in code. +var auth = 'admin:strongPassword@999'; // For testing only. Don't store credentials in code. var ca_certs_path = '/full/path/to/root-ca.pem'; // Optional client certificates if you don't want to use HTTP basic authentication. diff --git a/guides/advanced_index_actions.md b/guides/advanced_index_actions.md index faf5dc43d..da1776c0c 100644 --- a/guides/advanced_index_actions.md +++ b/guides/advanced_index_actions.md @@ -6,10 +6,11 @@ In this guide, we will look at some advanced index actions that are not covered Let's create a client instance, and an index named `movies`: ```javascript const { Client } = require('@opensearch-project/opensearch'); + const client = new Client({ - node: 'https://admin:admin@localhost:9200', - ssl: { rejectUnauthorized: false } + node: 'http://localhost:9200', }); + client.indices.create({index: 'movies'}) ``` ## API Actions diff --git a/guides/index_lifecycle.md b/guides/index_lifecycle.md index 4ecce6ad7..8c87cec95 100644 --- a/guides/index_lifecycle.md +++ b/guides/index_lifecycle.md @@ -3,23 +3,13 @@ This guide covers OpenSearch JavaScript Client API actions for Index Lifecycle. ## Setup -In this guide, we will need an OpenSearch cluster with more than one node. Let's use the sample [docker-compose.yml](https://opensearch.org/samples/docker-compose.yml) to start a cluster with two nodes. The cluster's API will be available at `localhost:9200` with basic authentication enabled with default username and password of `admin:admin`. - -To start the cluster, run the following command: - -```bash -cd /path/to/docker-compose.yml -docker-compose up -d -``` - -Let's create a client instance to access this cluster: +Let's create a client instance to access an OpenSearch cluster: ```javascript const { Client } = require('@opensearch-project/opensearch'); const client = new Client({ - node: 'https://admin:admin@localhost:9200', - ssl: { rejectUnauthorized: false } + node: 'http://localhost:9200', }); client.info().then(response => { diff --git a/guides/json.md b/guides/json.md index cfd5a1731..c1f395509 100644 --- a/guides/json.md +++ b/guides/json.md @@ -7,14 +7,7 @@ First, create a client instance with the following code to interact with an Open ```javascript const client = new Client({ - ssl: { - rejectUnauthorized: false, - }, - node: 'https://localhost:9200', - auth: { - username: 'admin', - password: 'admin', - }, + node: 'http://localhost:9200', }); ``` diff --git a/guides/msearch.md b/guides/msearch.md index 15f2cd36c..2d3352f0d 100644 --- a/guides/msearch.md +++ b/guides/msearch.md @@ -5,18 +5,8 @@ OpenSearch's Multi-Search (`msearch`) API allows you to execute multiple search # Setup ```javascript -const host = "localhost"; -const protocol = "https"; -const port = 9200; -const auth = "admin:admin"; -const ca_certs_path = "/full/path/to/root-ca.pem"; -const { Client } = require("@opensearch-project/opensearch"); -const fs = require("fs"); const client = new Client({ - node: `${protocol}://${auth}@${host}:${port}`, - ssl: { - ca: fs.readFileSync(ca_certs_path), - }, + node: 'http://localhost:9200', }); await client.bulk({ diff --git a/guides/search.md b/guides/search.md index 7e71f379f..66108780c 100644 --- a/guides/search.md +++ b/guides/search.md @@ -3,28 +3,8 @@ OpenSearch provides a powerful search API that allows you to search for document # Setup Let's start by creating an index and adding some documents to it: ```javascript -var host = "localhost"; -var protocol = "https"; -var port = 9200; -var auth = "admin:admin"; // For testing only. Don't store credentials in code. -var ca_certs_path = "/full/path/to/root-ca.pem"; - -// Optional client certificates if you don't want to use HTTP basic authentication. -// var client_cert_path = '/full/path/to/client.pem' -// var client_key_path = '/full/path/to/client-key.pem' - -// Create a client with SSL/TLS enabled. -var { Client } = require("@opensearch-project/opensearch"); -var fs = require("fs"); -var client = new Client({ - node: protocol + "://" + auth + "@" + host + ":" + port, - ssl: { - ca: fs.readFileSync(ca_certs_path), - // You can turn off certificate verification (rejectUnauthorized: false) if you're using - // self-signed certificates with a hostname mismatch. - // cert: fs.readFileSync(client_cert_path), - // key: fs.readFileSync(client_key_path) - }, +const client = new Client({ + node: 'http://localhost:9200', }); await client.indices.create({index: 'movies'}); diff --git a/lib/tools.d.ts b/lib/tools.d.ts new file mode 100644 index 000000000..f622023f1 --- /dev/null +++ b/lib/tools.d.ts @@ -0,0 +1,11 @@ +/* + * Copyright OpenSearch Contributors + * 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. + * + */ + +export function strongPasswordRequired(os_version?: string): boolean; diff --git a/lib/tools.js b/lib/tools.js new file mode 100644 index 000000000..cc3514f89 --- /dev/null +++ b/lib/tools.js @@ -0,0 +1,21 @@ +/* + * Copyright OpenSearch Contributors + * 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. + * + */ + +function strongPasswordRequired(os_version = process.env.OPENSEARCH_VERSION) { + // OpenSearch 2.12.X and later require strong passwords + if (os_version === undefined) + throw new Error('OPENSEARCH_VERSION environment variable is not set'); + if (os_version === 'latest') return true; + const [major, minor] = os_version.split('.'); + if (parseInt(major) > 2) return true; + return major === '2' && (minor === 'x' || parseInt(minor) >= 12); +} + +module.exports = { strongPasswordRequired }; diff --git a/test/integration/helper.js b/test/integration/helper.js index 6a1c56af2..7fb9178db 100644 --- a/test/integration/helper.js +++ b/test/integration/helper.js @@ -29,6 +29,22 @@ 'use strict'; +const { strongPasswordRequired } = require('../../lib/tools'); + +function createSecuredClient() { + const { Client } = require('../../'); + return new Client({ + ssl: { + rejectUnauthorized: false, + }, + node: 'https://localhost:9200', + auth: { + username: 'admin', + password: strongPasswordRequired() ? 'myStrongPassword123!' : 'admin', + }, + }); +} + function runInParallel(client, operation, options, clientOptions) { if (options.length === 0) return Promise.resolve(); const operations = options.map((opts) => { @@ -62,4 +78,4 @@ function to(promise) { const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); -module.exports = { runInParallel, delve, to, sleep }; +module.exports = { runInParallel, delve, to, sleep, createSecuredClient }; diff --git a/test/integration/helpers-secure/http.test.js b/test/integration/helpers-secure/http.test.js index 5d856b218..a587aa8d0 100644 --- a/test/integration/helpers-secure/http.test.js +++ b/test/integration/helpers-secure/http.test.js @@ -9,18 +9,9 @@ */ const { test } = require('tap'); -const { Client } = require('../../../'); +const { createSecuredClient } = require('../helper'); -const client = new Client({ - ssl: { - rejectUnauthorized: false, - }, - node: 'https://localhost:9200', - auth: { - username: 'admin', - password: 'admin', - }, -}); +const client = createSecuredClient(); const http = client.http; const index = 'books'; diff --git a/test/integration/helpers-secure/search.test.js b/test/integration/helpers-secure/search.test.js index 0e3ff61d3..c0f708b07 100644 --- a/test/integration/helpers-secure/search.test.js +++ b/test/integration/helpers-secure/search.test.js @@ -14,20 +14,10 @@ const { createReadStream } = require('fs'); const { join } = require('path'); const split = require('split2'); const { test, beforeEach, afterEach } = require('tap'); - -const { Client } = require('../../..'); +const { createSecuredClient } = require('../helper'); const INDEX = `test-helpers-${process.pid}`; -const client = new Client({ - ssl: { - rejectUnauthorized: false, - }, - node: 'https://localhost:9200', - auth: { - username: 'admin', - password: 'admin', - }, -}); +const client = createSecuredClient(); beforeEach(async () => { await client.indices.create({ index: INDEX }); diff --git a/test/integration/helpers-secure/security.test.js b/test/integration/helpers-secure/security.test.js index 2b29d92c3..a922588ba 100644 --- a/test/integration/helpers-secure/security.test.js +++ b/test/integration/helpers-secure/security.test.js @@ -9,18 +9,9 @@ */ const { test } = require('tap'); -const { Client } = require('../../../'); +const { createSecuredClient } = require('../helper'); -const client = new Client({ - ssl: { - rejectUnauthorized: false, - }, - node: 'https://localhost:9200', - auth: { - username: 'admin', - password: 'admin', - }, -}); +const client = createSecuredClient(); const security = client.security; test('Security: User', async (t) => { diff --git a/test/unit/tools.test.js b/test/unit/tools.test.js new file mode 100644 index 000000000..53264d8b0 --- /dev/null +++ b/test/unit/tools.test.js @@ -0,0 +1,30 @@ +/* + * Copyright OpenSearch Contributors + * 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. + * + */ + +'use strict'; + +const { test } = require('tap'); +const { strongPasswordRequired } = require('../../lib/tools'); + +test('strongPasswordRequired', (t) => { + t.plan(9); + + t.throws(() => strongPasswordRequired()); + + t.ok(strongPasswordRequired('latest')); + t.ok(strongPasswordRequired('3.0')); + t.ok(strongPasswordRequired('2.12.x')); + t.ok(strongPasswordRequired('2.12.0')); + + t.notOk(strongPasswordRequired('2.11')); + t.notOk(strongPasswordRequired('2.11.x')); + t.notOk(strongPasswordRequired('1.13.0')); + t.notOk(strongPasswordRequired('1.x')); +}); From e4e6c7f1090ddbe32161825c47bde6089cb06164 Mon Sep 17 00:00:00 2001 From: Theo Truong Date: Tue, 30 Jan 2024 14:28:59 -0700 Subject: [PATCH 2/2] # moved OPENSEARCH_VERSION to global scope Signed-off-by: Theo Truong --- .github/workflows/integration.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index c2471433d..86163836f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -10,6 +10,9 @@ on: paths-ignore: - '**/*.md' +env: + OPENSEARCH_VERSION: latest + jobs: helpers-integration-test: name: Helpers integration test @@ -20,7 +23,6 @@ jobs: node-version: [10.x, 12.x, 14.x, 16.x, 18.x] env: - OPENSEARCH_VERSION: latest SECURE_INTEGRATION: false steps: @@ -70,7 +72,6 @@ jobs: node-version: [10.x, 12.x, 14.x, 16.x, 18.x] env: - OPENSEARCH_VERSION: latest SECURE_INTEGRATION: true steps: