Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AppStream feat branch with latest code from develop #585

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [3.3.0](https://github.com/awslabs/service-workbench-on-aws/compare/v3.2.0...v3.3.0) (2021-06-25)

### Documentation

* Service Workbench installation guide ([#545](https://github.com/awslabs/service-workbench-on-aws/issues/545)) ([2be27d1](https://github.com/awslabs/service-workbench-on-aws/commit/2be27d16da5a4c0405648b220a548415eed47ef7))
## [3.2.0](https://github.com/awslabs/service-workbench-on-aws/compare/v3.1.0...v3.2.0) (2021-06-11)


### Features

* Add warning that internal authentication shouldn't be used in production ([#506](https://github.com/awslabs/service-workbench-on-aws/issues/506)) ([1586278](https://github.com/awslabs/service-workbench-on-aws/commit/15862785fb0ade825c251902bd13dea948833c19))
* Encrypt s3 buckets for EMR log bucket and CICD Artifact bucket ([#508](https://github.com/awslabs/service-workbench-on-aws/issues/508)) ([e86fd06](https://github.com/awslabs/service-workbench-on-aws/commit/e86fd0668aa6971e09491ab090586ce825f51069))
* study permissions only shown to Study Admin ([#501](https://github.com/awslabs/service-workbench-on-aws/issues/501)) ([f3eaae8](https://github.com/awslabs/service-workbench-on-aws/commit/f3eaae802c838b92fe95deea3dd4a3ac23c89d3b))


### Bug Fixes

* add termination status for non-found workspaces ([#502](https://github.com/awslabs/service-workbench-on-aws/issues/502)) ([8c30378](https://github.com/awslabs/service-workbench-on-aws/commit/8c30378dd25c02abd3bb3a250a68eccee3b7bca3))
* adds 'stopped' filter for workspaces ([960b592](https://github.com/awslabs/service-workbench-on-aws/commit/960b592341b186f09da12307cca138fd0b4fde25))
* Allow sagemaker to have the proper IAM permission to autostop itself ([#515](https://github.com/awslabs/service-workbench-on-aws/issues/515)) ([32007ed](https://github.com/awslabs/service-workbench-on-aws/commit/32007edb95ee411a0cc4a302c0af247e54d438a0))
* Corrected Spark defaults to fix read/write functionality from Spark ([#526](https://github.com/awslabs/service-workbench-on-aws/issues/526)) ([f96e1bd](https://github.com/awslabs/service-workbench-on-aws/commit/f96e1bde4f535c79b81490888436c9dfb49045c9))
* Do not allow users to change root password ([#503](https://github.com/awslabs/service-workbench-on-aws/issues/503)) ([a436f73](https://github.com/awslabs/service-workbench-on-aws/commit/a436f73bcbf8c9c23bed7ebaa11837ca13628ccb))
* moved notification boxes to avoid blocking the top ribbon. ([#483](https://github.com/awslabs/service-workbench-on-aws/issues/483)) ([5a226d7](https://github.com/awslabs/service-workbench-on-aws/commit/5a226d7a46ccae2d9f741dbeffe24d78e8dad252))
* react compilation error ([#500](https://github.com/awslabs/service-workbench-on-aws/issues/500)) ([547f2ad](https://github.com/awslabs/service-workbench-on-aws/commit/547f2ad9e1d3abfb61dfecc73268da541f243aad))
* Redirect non admin users to "/" if they try to access "/users" ([#489](https://github.com/awslabs/service-workbench-on-aws/issues/489)) ([ee3a58e](https://github.com/awslabs/service-workbench-on-aws/commit/ee3a58e864f2f620358a34063afcbb02adde687c))

## [3.1.0](https://github.com/awslabs/service-workbench-on-aws/compare/v3.0.0...v3.1.0) (2021-05-10)

### Features
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Read the Service Workbench Deployment Guide provided in the installation. You ca
npm install -g pnpm
```

- **Go:** You also need to install [Go](https://golang.org/doc/install). `Go` is used for creating a multipart S3 downloader tool that is used in AWS Service Catalog EC2 Windows based research environments.
- **Go:** You also need to install [Go 1.13.7](https://golang.org/doc/install) or later. `Go` is used for creating a multipart S3 downloader tool that is used in AWS Service Catalog EC2 Windows based research environments.

For more information, refer to the **Prerequisites** section of the Service Workbench Deployment Guide.

Expand Down Expand Up @@ -157,7 +157,7 @@ cd -
```

---

For more information, refer to *Service Workbench Installation Guide*.

## Using Service Workbench

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,13 @@ Resources:
yarn.nodemanager.vmem-check-enabled: false
- Classification: spark-defaults
ConfigurationProperties:
spark.hadoop.io.compression.codecs: 'org.apache.hadoop.io.compress.DefaultCodec,is.hail.io.compress.BGzipCodec,org.apache.hadoop.io.compress.GzipCodec'
spark.hadoop.io.compression.codecs: 'org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.GzipCodec'
spark.serializer: 'org.apache.spark.serializer.KryoSerializer'
spark.hadoop.parquet.block.size: '1099511627776'
spark.sql.files.maxPartitionBytes: '1099511627776'
spark.sql.files.openCostInBytes: '1099511627776'
# Defaults picked from spark conf
# https://github.com/apache/spark/blob/878527d9fae8945d087ec871bb0a5f49b6341939/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala#L1322-L1339
spark.hadoop.parquet.block.size: '134217728' # 128MB
spark.sql.files.maxPartitionBytes: '134217728' # 128 MB
spark.sql.files.openCostInBytes: '4194304' # 4 MB
Configurations: []
Instances:
AdditionalMasterSecurityGroups:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#### Tools

- Node 12
- Node 12.x or later
- [Hashicorp Packer](https://www.packer.io/)
- The Service Workbench code is tested with Packer 1.6.0. You can install Packer 1.6.0 by using Packer version manager [pkenv](https://github.com/iamhsa/pkenv).

Expand Down
12 changes: 12 additions & 0 deletions addons/addon-base-ui/packages/base-ui/src/AppContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,20 @@ class AppContainer extends Component {
return false; // This will stop lodash from continuing the forEach loop
});

plugins = _.reverse(pluginRegistry.getPluginsWithMethod('app-component', 'getForceLogoutComponent') || []);
let ForceLogout = () => <></>;
// We ask each plugin in reverse order if they have the ForceLogout component
_.forEach(plugins, plugin => {
const result = plugin.getForceLogoutComponent({ location, appContext: getEnv(app) });
if (_.isUndefined(result)) return;
ForceLogout = result;
// eslint-disable-next-line consistent-return
return false; // This will stop lodash from continuing the forEach loop
});

return (
<>
<ForceLogout />
<AutoLogout />
<App />
</>
Expand Down
119 changes: 119 additions & 0 deletions addons/addon-base-ui/packages/base-ui/src/parts/ForceLogout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import _ from 'lodash';
import React from 'react';
import { observable, action, decorate, computed, runInAction } from 'mobx';
import { observer, inject } from 'mobx-react';
import { Button, Modal } from 'semantic-ui-react';

const jwtDecode = require('jwt-decode');

// expected props
// - authentication
// - app
class ForceLogout extends React.Component {
constructor(props) {
super(props);
runInAction(() => {
this.tokenActive = true;
});
}

get app() {
return this.props.app;
}

get authentication() {
return this.props.authentication;
}

get modalOpen() {
return !this.tokenActive;
}

componentDidMount() {
this.timer = setInterval(() => {
runInAction(() => {
this.tokenActive = !this.hasTokenExpired();
});
}, 1000);
}

componentWillUnmount() {
clearInterval(this.timer);
}

doLogout = async () => {
clearInterval(this.timer);
return this.authentication.logout({ autoLogout: true });
};

hasTokenExpired = () => {
try {
const idToken = localStorage.getItem('appIdToken');
const decodedIdToken = jwtDecode(idToken);
const expiresAt = _.get(decodedIdToken, 'exp', 0) * 1000;
// The next line computes how many minutes are left until token expiration
return (expiresAt - Date.now()) / 60 / 1000 < 0;
} catch (e) {
return false;
}
};

handleLogout = async event => {
event.preventDefault();
event.stopPropagation();
return this.doLogout();
};

renderModal() {
if (this.tokenActive) {
return null;
}
return (
<>
<Modal open={this.modalOpen} closeOnEscape={false} closeOnDimmerClick={false} centered={false}>
<Modal.Header>Session expired</Modal.Header>
<Modal.Content className="center">
<div>Your session has expired. Close Service Workbench and log in again.</div>
</Modal.Content>
<Modal.Actions className="clearfix">
<Button floated="right" content="Log Out" onClick={this.handleLogout} />
</Modal.Actions>
</Modal>
</>
);
}

render() {
const authenticated = this.app.userAuthenticated;
if (!authenticated) return null;
return <>{this.renderModal()}</>;
}
}

// see https://medium.com/@mweststrate/mobx-4-better-simpler-faster-smaller-c1fbc08008da
decorate(ForceLogout, {
app: computed,
authentication: computed,
modalOpen: computed,
tokenActive: observable,
doLogout: action,
handleLogout: action,
clearInterval: action,
});

export default inject('authentication', 'app')(observer(ForceLogout));
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import React from 'react';
import { shallow } from 'enzyme';
import { Button, Modal } from 'semantic-ui-react';
import ForceLogout from '../ForceLogout';

const AuthenticationProviderConfigsStore = { logout: jest.fn() };
const app = { userAuthenticated: true };
describe('ForceLogout', () => {
let wrapper = null;
let renderModalSnapshot = null;
let renderSnapshot = null;
beforeAll(() => {
wrapper = shallow(<ForceLogout.wrappedComponent authentication={AuthenticationProviderConfigsStore} app={app} />);
const component = wrapper.instance();
component.tokenActive = false;
renderModalSnapshot = (
<>
<Modal open={component.modalOpen} closeOnEscape={false} closeOnDimmerClick={false} centered={false}>
<Modal.Header>Session expired</Modal.Header>
<Modal.Content className="center">
<div>Your session has expired. Close Service Workbench and log in again.</div>
</Modal.Content>
<Modal.Actions className="clearfix">
<Button floated="right" content="Log Out" onClick={component.handleLogout} />
</Modal.Actions>
</Modal>
</>
);
renderSnapshot = (
<>
<>
<Modal open={component.modalOpen} closeOnEscape={false} closeOnDimmerClick={false} centered={false}>
<Modal.Header>Session expired</Modal.Header>
<Modal.Content className="center">
<div>Your session has expired. Close Service Workbench and log in again.</div>
</Modal.Content>
<Modal.Actions className="clearfix">
<Button floated="right" content="Log Out" onClick={component.handleLogout} />
</Modal.Actions>
</Modal>
</>
</>
);
});

it('should exist', () => {
expect(ForceLogout).not.toBeNull();
expect(ForceLogout.displayName).toBe('inject-with-authentication-app(ForceLogout)');
});

it('should make renderModal return null when tokenActive is true', () => {
const component = wrapper.instance();
component.tokenActive = true;
expect(component.renderModal()).toEqual(null);
});

it('should make renderModal return modal when tokenActive is false', () => {
const component = wrapper.instance();
component.tokenActive = false;
expect(component.renderModal()).toEqual(renderModalSnapshot);
});

it('should make render return modal when user is authenticated', () => {
const component = wrapper.instance();
expect(component.render()).toEqual(renderSnapshot);
});

it('should make render return null when user is not authenticated', () => {
const userAuth = { userAuthenticated: false };
const tempWrapper = shallow(
<ForceLogout.wrappedComponent authentication={AuthenticationProviderConfigsStore} app={userAuth} />,
);
const component = tempWrapper.instance();
expect(component.render()).toEqual(null);
clearInterval(component.timer);
});

afterAll(async () => {
const component = wrapper.instance();
clearInterval(component.timer);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import App from '../App';
import AutoLogout from '../parts/AutoLogout';
import ForceLogout from '../parts/ForceLogout';

// eslint-disable-next-line no-unused-vars
function getAppComponent({ location, appContext }) {
Expand All @@ -26,9 +27,15 @@ function getAutoLogoutComponent({ location, appContext }) {
return AutoLogout;
}

// eslint-disable-next-line no-unused-vars
function getForceLogoutComponent({ location, appContext }) {
return ForceLogout;
}

const plugin = {
getAppComponent,
getAutoLogoutComponent,
getForceLogoutComponent,
};

export default plugin;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#### Tools

- Node 12+
- Node 12.x or later
- AWS CLI

#### Project variables
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ This package is a Serverless plugin that will build golang code and upload it to

#### Tools

- Node 12
- Go
- Node 12.x or later
- Go 1.13.7 or later

## Configuration

Expand Down
Binary file added docs.zip
Binary file not shown.
26 changes: 26 additions & 0 deletions docs/docs/configuration_guide/activedirectory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
id: activedirectory
title: Configuring Service Workbench using Microsoft Active Directory
sidebar_label: Configuring Service Workbench using Microsoft Active Directory
---
import useBaseUrl from '@docusaurus/useBaseUrl';

### Updating accounts

You can use Microsoft Active Directory to create and manage domains, users, and objects within a network. It provides a way to organize a large number of users into logical groups and subgroups. It also provides access control at each level. For more information about IdPs, see [Identity Providers](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/identity-providers).

Microsoft Active Directory (or any IdP) is a source of authentication. It authenticates users for Service Workbench login. After successful Active Directory login, it sends user information to an Amazon Cognito user pool created by Service Workbench. Service Workbench then uses the Amazon Cognito user pool for its internal use as described in [Service Workbench and IdP workflow](/configuration_guide/workflow).

To configure Active Directory authentication:

1. Create an IdP if you don’t have one. For more information about creating an IdP, see [sign up your organization](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/sign-up-organization).
2. Download SAML metadata (XML file).
3. Using Amazon Cognito on the AWS Management Console, create an Amazon Cognito user pool. The name of the pool must be `<stage>-<solution_name>-userPool`, where`stage` and `solution_name` are configured in the main configuration file.
4. Gather the relying party information, such as `User Pool Id`, `Relying Party Id`, and `User Pool Signing Cert`.
5. Run the following script from the root of Service Workbench repository:
`scripts/get-relying-party.sh`
6. Copy the output of this script and provide it to your Active Directory administrator.

<img src={useBaseUrl('img/deployment/post_deployment/scripts.png')} />

**Figure: Script output**
Loading