From ee26edc720544e749087ea186f6d3331244c41fa Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:46:46 -0700 Subject: [PATCH] [MD] Add data source signing support (#2510) (#2547) * Add data source signing support * Optimize error handling and logging * Update wording on error message and readme Signed-off-by: Louis Chu (cherry picked from commit e3bbdefb34895b58079f36380f35067cbceba198) Co-authored-by: Louis Chu --- .../cryptography/cryptography_client.test.ts | 117 ------------------ .../cryptography/cryptography_client.ts | 70 ----------- .../data_source/server/cryptography/index.ts | 6 - 3 files changed, 193 deletions(-) delete mode 100644 src/plugins/data_source/server/cryptography/cryptography_client.test.ts delete mode 100644 src/plugins/data_source/server/cryptography/cryptography_client.ts delete mode 100644 src/plugins/data_source/server/cryptography/index.ts diff --git a/src/plugins/data_source/server/cryptography/cryptography_client.test.ts b/src/plugins/data_source/server/cryptography/cryptography_client.test.ts deleted file mode 100644 index 1f8d2596a3c4..000000000000 --- a/src/plugins/data_source/server/cryptography/cryptography_client.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { CryptographyClient } from './cryptography_client'; -import { randomBytes } from 'crypto'; - -const dummyWrappingKeyName = 'dummy_wrapping_key_name'; -const dummyWrappingKeyNamespace = 'dummy_wrapping_key_namespace'; - -test('Invalid wrapping key size throws error', () => { - const dummyRandomBytes = [...randomBytes(31)]; - const expectedErrorMsg = `Wrapping key size shoule be 32 bytes, as used in envelope encryption. Current wrapping key size: '${dummyRandomBytes.length}' bytes`; - expect(() => { - new CryptographyClient(dummyWrappingKeyName, dummyWrappingKeyNamespace, dummyRandomBytes); - }).toThrowError(new Error(expectedErrorMsg)); -}); - -describe('Test encrpyt and decrypt module', () => { - const dummyPlainText = 'dummy'; - const dummyNumArray1 = [...randomBytes(32)]; - const dummyNumArray2 = [...randomBytes(32)]; - - describe('Positive test cases', () => { - test('Encrypt and Decrypt with same in memory keyring', async () => { - const cryptographyClient = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - const encrypted = await cryptographyClient.encryptAndEncode(dummyPlainText); - const outputText = await cryptographyClient.decodeAndDecrypt(encrypted); - expect(outputText).toBe(dummyPlainText); - }); - test('Encrypt and Decrypt with two different keyrings with exact same identifiers', async () => { - const cryptographyClient1 = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - const encrypted = await cryptographyClient1.encryptAndEncode(dummyPlainText); - - const cryptographyClient2 = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - const outputText = await cryptographyClient2.decodeAndDecrypt(encrypted); - expect(cryptographyClient1 === cryptographyClient2).toBeFalsy(); - expect(outputText).toBe(dummyPlainText); - }); - }); - - describe('Negative test cases', () => { - const defaultWrappingKeyName = 'changeme'; - const defaultWrappingKeyNamespace = 'changeme'; - const expectedErrorMsg = 'unencryptedDataKey has not been set'; - test('Encrypt and Decrypt with different key names', async () => { - const cryptographyClient1 = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - const encrypted = await cryptographyClient1.encryptAndEncode(dummyPlainText); - - const cryptographyClient2 = new CryptographyClient( - defaultWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - try { - await cryptographyClient2.decodeAndDecrypt(encrypted); - } catch (error) { - expect(error.message).toMatch(expectedErrorMsg); - } - }); - test('Encrypt and Decrypt with different key namespaces', async () => { - const cryptographyClient1 = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - const encrypted = await cryptographyClient1.encryptAndEncode(dummyPlainText); - - const cryptographyClient2 = new CryptographyClient( - dummyWrappingKeyName, - defaultWrappingKeyNamespace, - dummyNumArray1 - ); - try { - await cryptographyClient2.decodeAndDecrypt(encrypted); - } catch (error) { - expect(error.message).toMatch(expectedErrorMsg); - } - }); - test('Encrypt and Decrypt with different wrapping keys', async () => { - const cryptographyClient1 = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray1 - ); - const encrypted = await cryptographyClient1.encryptAndEncode(dummyPlainText); - - const cryptographyClient2 = new CryptographyClient( - dummyWrappingKeyName, - dummyWrappingKeyNamespace, - dummyNumArray2 - ); - try { - await cryptographyClient2.decodeAndDecrypt(encrypted); - } catch (error) { - expect(error.message).toMatch(expectedErrorMsg); - } - }); - }); -}); diff --git a/src/plugins/data_source/server/cryptography/cryptography_client.ts b/src/plugins/data_source/server/cryptography/cryptography_client.ts deleted file mode 100644 index f5968ae13adb..000000000000 --- a/src/plugins/data_source/server/cryptography/cryptography_client.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - buildClient, - CommitmentPolicy, - RawAesKeyringNode, - RawAesWrappingSuiteIdentifier, -} from '@aws-crypto/client-node'; - -export const ENCODING_STRATEGY: BufferEncoding = 'base64'; -export const WRAPPING_KEY_SIZE: number = 32; - -export class CryptographyClient { - private readonly commitmentPolicy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT; - private readonly wrappingSuite = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING; - - private keyring: RawAesKeyringNode; - - private readonly encrypt: Function; - private readonly decrypt: Function; - - /** - * @param {string} wrappingKeyName name value to identify the AES key in a keyring - * @param {string} wrappingKeyNamespace namespace value to identify the AES key in a keyring, - * @param {number[]} wrappingKey 32 Bytes raw wrapping key used to perform envelope encryption - */ - constructor(wrappingKeyName: string, wrappingKeyNamespace: string, wrappingKey: number[]) { - if (wrappingKey.length !== WRAPPING_KEY_SIZE) { - const wrappingKeySizeMismatchMsg = `Wrapping key size shoule be 32 bytes, as used in envelope encryption. Current wrapping key size: '${wrappingKey.length}' bytes`; - throw new Error(wrappingKeySizeMismatchMsg); - } - - // Create raw AES keyring - this.keyring = new RawAesKeyringNode({ - keyName: wrappingKeyName, - keyNamespace: wrappingKeyNamespace, - unencryptedMasterKey: new Uint8Array(wrappingKey), - wrappingSuite: this.wrappingSuite, - }); - - // Destructuring encrypt and decrypt functions from client - const { encrypt, decrypt } = buildClient(this.commitmentPolicy); - - this.encrypt = encrypt; - this.decrypt = decrypt; - } - - /** - * Input text content and output encrypted string encoded with ENCODING_STRATEGY - * @param {string} plainText - * @returns {Promise} - */ - public async encryptAndEncode(plainText: string): Promise { - const result = await this.encrypt(this.keyring, plainText); - return result.result.toString(ENCODING_STRATEGY); - } - - /** - * Input encrypted content and output decrypted string - * @param {string} encrypted - * @returns {Promise} - */ - public async decodeAndDecrypt(encrypted: string): Promise { - const result = await this.decrypt(this.keyring, Buffer.from(encrypted, ENCODING_STRATEGY)); - return result.plaintext.toString(); - } -} diff --git a/src/plugins/data_source/server/cryptography/index.ts b/src/plugins/data_source/server/cryptography/index.ts deleted file mode 100644 index 857fa691bddf..000000000000 --- a/src/plugins/data_source/server/cryptography/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { CryptographyClient } from './cryptography_client';