Skip to content

Commit

Permalink
Add encrypt/decrypt module on data source plugin (opensearch-project#…
Browse files Browse the repository at this point in the history
…2120)

Signed-off-by: Louis Chu <clingzhi@amazon.com>

1. Add encrypt/decrypt module with UT
2. Add client factory wrapper for encrypt credential
3. Add encryption config support
4. Bugfix on Jest interpret Buffer

Signed-off-by: Kristen Tian <tyarong@amazon.com>
  • Loading branch information
noCharger authored and kristenTian committed Sep 15, 2022
1 parent 0019d2d commit 72d9b1a
Show file tree
Hide file tree
Showing 19 changed files with 570 additions and 43 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
]
},
"dependencies": {
"@aws-crypto/client-node": "^3.1.1",
"@elastic/datemath": "5.0.3",
"@elastic/eui": "npm:@opensearch-project/oui@1.0.0",
"@elastic/good": "^9.0.1-kibana3",
Expand Down
3 changes: 3 additions & 0 deletions src/dev/jest/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,7 @@ export default {
'<rootDir>/node_modules/enzyme-to-json/serializer',
],
reporters: ['default', '<rootDir>/src/dev/jest/junit_reporter.js'],
globals: {
Uint8Array: Uint8Array,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@ import {
EuiFieldPassword,
} from '@elastic/eui';
import { DocLinksStart } from 'src/core/public';
import { Credential } from '../../../../data_source/common';

import { getCreateBreadcrumbs } from '../breadcrumbs';
import { CredentialManagmentContextValue } from '../../types';
import { Header } from './components/header';
import { context as contextType } from '../../../../opensearch_dashboards_react/public';

interface CreateCredentialWizardState {
credentialName: string;
authType: string;
credentialMaterialsType: string;
userName: string;
password: string;
credentialName?: string;
credentialMaterialsType?: string;
username?: string;
password?: string;
dual: boolean;
toasts: EuiGlobalToastListToast[];
docLinks: DocLinksStart;
Expand All @@ -49,11 +50,10 @@ export class CreateCredentialWizard extends React.Component<
context.services.setBreadcrumbs(getCreateBreadcrumbs());

this.state = {
credentialName: '',
authType: 'shared',
credentialMaterialsType: 'username_password_credential',
userName: '',
password: '',
credentialName: undefined,
credentialMaterialsType: undefined,
username: undefined,
password: undefined,
dual: true,
toasts: [],
docLinks: context.services.docLinks,
Expand All @@ -71,8 +71,11 @@ export class CreateCredentialWizard extends React.Component<
const header = this.renderHeader();

const options = [
{ value: 'username_password_credential', text: 'Username and Password Credential' },
{ value: 'no_auth', text: 'No Auth' },
{ value: undefined, text: 'Select Credential Materials Type' },
{
value: Credential.CredentialMaterialsType.UsernamePasswordType,
text: 'Username and Password Credential',
},
];

return (
Expand Down Expand Up @@ -127,15 +130,15 @@ export class CreateCredentialWizard extends React.Component<
<EuiFormRow label="User Name">
<EuiFieldText
placeholder="Your User Name"
value={this.state.userName || ''}
onChange={(e) => this.setState({ userName: e.target.value })}
value={this.state.username || undefined}
onChange={(e) => this.setState({ username: e.target.value })}
/>
</EuiFormRow>
<EuiFormRow label="Password">
<EuiFieldPassword
placeholder="Your Password"
type={this.state.dual ? 'dual' : undefined}
value={this.state.password || ''}
value={this.state.password || undefined}
onChange={(e) => this.setState({ password: e.target.value })}
/>
</EuiFormRow>
Expand Down Expand Up @@ -177,11 +180,10 @@ export class CreateCredentialWizard extends React.Component<
// TODO: Add rendering spanner https://github.com/opensearch-project/OpenSearch-Dashboards/issues/2050
await savedObjects.client.create('credential', {
title: this.state.credentialName,
authType: this.state.authType,
credentialMaterials: {
credentialMaterialsType: this.state.credentialMaterialsType,
credentialMaterialsContent: {
userName: this.state.userName,
username: this.state.username,
password: this.state.password,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { useEffectOnce } from 'react-use';

import { i18n } from '@osd/i18n';
import { FormattedMessage } from '@osd/i18n/react';
Expand Down Expand Up @@ -41,7 +42,7 @@ const pagination = {

const sorting = {
sort: {
field: 'credentialName',
field: 'title',
direction: 'asc' as const,
},
};
Expand All @@ -68,7 +69,11 @@ export const CredentialsTable = ({ canSave, history }: Props) => {
const [selectedCredentials, setSelectedCredentials] = React.useState<CredentialsTableItem[]>([]);

const { setBreadcrumbs } = useOpenSearchDashboards<CredentialManagementContext>().services;
setBreadcrumbs(getListBreadcrumbs());

/* Update breadcrumb*/
useEffectOnce(() => {
setBreadcrumbs(getListBreadcrumbs());
});

const { savedObjects, uiSettings } = useOpenSearchDashboards<
CredentialManagementContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ import {
EuiConfirmModal,
} from '@elastic/eui';
import { DocLinksStart } from 'src/core/public';
import { Credential } from '../../../../data_source/common';

import { getCreateBreadcrumbs } from '../breadcrumbs';
import { CredentialManagmentContextValue } from '../../types';
// TODO: Add Header https://github.com/opensearch-project/OpenSearch-Dashboards/issues/2051
import { context as contextType } from '../../../../opensearch_dashboards_react/public';
import { CredentialEditPageItem } from '../types';
import * as localizedContent from '../text_content/text_content';
import { localizedContent } from '../text_content';

interface EditCredentialState {
credentialName: string;
credentialMaterialsType: string;
userName: string;
password: string;
username?: string;
password?: string;
dual: boolean;
toasts: EuiGlobalToastListToast[];
docLinks: DocLinksStart;
Expand All @@ -61,8 +63,8 @@ export class EditCredentialComponent extends React.Component<
this.state = {
credentialName: props.credential.title,
credentialMaterialsType: props.credential.credentialMaterialsType,
userName: '',
password: '',
username: undefined,
password: undefined,
dual: true,
toasts: [],
docLinks: context.services.docLinks,
Expand Down Expand Up @@ -140,10 +142,9 @@ export class EditCredentialComponent extends React.Component<
renderContent() {
const options = [
{
value: 'username_password_credential',
value: Credential.CredentialMaterialsType.UsernamePasswordType,
text: 'Username and Password Credential',
},
{ value: 'no_auth', text: 'No Auth' },
];

return (
Expand Down Expand Up @@ -198,15 +199,15 @@ export class EditCredentialComponent extends React.Component<
<EuiFormRow label="User Name">
<EuiFieldText
placeholder="Your User Name"
value={this.state.userName || ''}
onChange={(e) => this.setState({ userName: e.target.value })}
value={this.state.username || undefined}
onChange={(e) => this.setState({ username: e.target.value })}
/>
</EuiFormRow>
<EuiFormRow label="Password">
<EuiFieldPassword
placeholder="Your Password"
type={this.state.dual ? 'dual' : undefined}
value={this.state.password || ''}
value={this.state.password || undefined}
onChange={(e) => this.setState({ password: e.target.value })}
/>
</EuiFormRow>
Expand Down Expand Up @@ -254,7 +255,7 @@ export class EditCredentialComponent extends React.Component<
credentialMaterials: {
credentialMaterialsType: this.state.credentialMaterialsType,
credentialMaterialsContent: {
userName: this.state.userName,
username: this.state.username,
password: this.state.password,
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * as localizedContent from '../text_content/text_content';
3 changes: 2 additions & 1 deletion src/plugins/credential_management/public/components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export async function getCredentials(savedObjectsClient: SavedObjectsClientContr
.map((source) => {
const id = source.id;
const title = source.get('title');
const credentialMaterialsType = source.get('credentialMaterials').credentialMaterialsType;
const credentialMaterialsType = source.get('credentialMaterials')
?.credentialMaterialsType;
return {
id,
title,
Expand Down
6 changes: 6 additions & 0 deletions src/plugins/data_source/common/credentials/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * as Credential from './types';
29 changes: 29 additions & 0 deletions src/plugins/data_source/common/credentials/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { SavedObjectAttributes } from 'src/core/types';

/**
* Each credential's materials type. For the time being, only username/password pairs are supported.
*/
export enum CredentialMaterialsType {
UsernamePasswordType = 'username_password',
}

export interface CredentialSavedObjectAttributes extends SavedObjectAttributes {
title: string;
credentialMaterials: CredentialMaterials;
description?: string;
}

export interface CredentialMaterials extends SavedObjectAttributes {
credentialMaterialsType: CredentialMaterialsType;
credentialMaterialsContent: UsernamePasswordTypedContent;
}

export interface UsernamePasswordTypedContent extends SavedObjectAttributes {
username: string;
password: string;
}
2 changes: 2 additions & 0 deletions src/plugins/data_source/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@

export const PLUGIN_ID = 'dataSource';
export const PLUGIN_NAME = 'data_source';

export { Credential } from './credentials';
34 changes: 34 additions & 0 deletions src/plugins/data_source/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { schema, TypeOf } from '@osd/config-schema';

const KEY_NAME_MIN_LENGTH: number = 1;
const KEY_NAME_MAX_LENGTH: number = 100;
// Wrapping key size shoule be 32 bytes, as used in envelope encryption algorithms.
const WRAPPING_KEY_SIZE: number = 32;

export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: false }),
encryption: schema.object({
wrappingKeyName: schema.string({
minLength: KEY_NAME_MIN_LENGTH,
maxLength: KEY_NAME_MAX_LENGTH,
defaultValue: 'changeme',
}),
wrappingKeyNamespace: schema.string({
minLength: KEY_NAME_MIN_LENGTH,
maxLength: KEY_NAME_MAX_LENGTH,
defaultValue: 'changeme',
}),
wrappingKey: schema.arrayOf(schema.number(), {
minSize: WRAPPING_KEY_SIZE,
maxSize: WRAPPING_KEY_SIZE,
defaultValue: new Array(32).fill(0),
}),
}),
});

export type DataSourcePluginConfigType = TypeOf<typeof configSchema>;
Loading

0 comments on commit 72d9b1a

Please sign in to comment.