Skip to content

Commit

Permalink
feat(core): ssm policy helper
Browse files Browse the repository at this point in the history
Fixes #265
  • Loading branch information
horsmand committed Dec 9, 2020
1 parent 510eb86 commit 4b3146f
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 15 deletions.
15 changes: 10 additions & 5 deletions examples/deadline/All-In-AWS-Infrastructure-Basic/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ These instructions assume that your working directory is `examples/deadline/All-
popd
pip install ../../../../dist/python/aws-rfdk-<version>.tar.gz
```
4. Change the value in the `deadline_client_linux_ami_map` variable in `package/config.py` to include the region + AMI ID mapping of your EC2 AMI(s) with Deadline Worker.
4. Change the value in the `deadline_client_linux_ami_map` variable in `package/config.py` to include the region + AMI ID mapping of your EC2 AMI(s) with Deadline Worker. You can use the follow AWS CLI query to find AMI ID's:
```bash
aws --region <region> ec2 describe-images \
--owners 357466774442 \
--filters "Name=name,Values=*Worker*" "Name=name,Values=*<version>*" \
--query 'Images[*].[ImageId, Name]' \
--output text
```
And enter it into this section of `package/config.py`:
```python
# For example, in the us-west-2 region
self.deadline_client_linux_ami_map: Mapping[str, str] = {
Expand Down Expand Up @@ -104,10 +112,7 @@ These instructions assume that your working directory is `examples/deadline/All-
# Set this value to the version of AWS Thinkbox Deadline you'd like to deploy to your farm. Deadline 10.1.9 and up are supported.
RFDK_DEADLINE_VERSION=<version_of_deadline>
npx --package=aws-rfdk@${RFDK_VERSION} stage-deadline \
--deadlineInstallerURI s3://thinkbox-installers/Deadline/${RFDK_DEADLINE_VERSION}/Linux/DeadlineClient-${RFDK_DEADLINE_VERSION}-linux-x64-installer.run \
--dockerRecipesURI s3://thinkbox-installers/DeadlineDocker/${RFDK_DEADLINE_VERSION}/DeadlineDocker-${RFDK_DEADLINE_VERSION}.tar.gz \
--output stage
npx --package=aws-rfdk@${RFDK_VERSION} stage-deadline ${RFDK_DEADLINE_VERSION} --output stage
```
12. Deploy all the stacks in the sample app:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ class AppConfig:
TODO: Fill these in with your own values.
"""
def __init__(self):
# A map of regions to Deadline Client Linux AMIs.
self.deadline_client_linux_ami_map: Mapping[str, str] = {'region': 'ami-id'}
# A map of regions to Deadline Client Linux AMIs.As an example, the Linux Deadline 10.1.12.1 AMI ID
# from us-west-2 is filled in. It can be used as-is, added to, or replaced. Ideally the version here
# should match the one used for staging the render queue and usage based licensing recipes.
self.deadline_client_linux_ami_map: Mapping[str, str] = {'us-west-2': 'ami-039f0c1faba28b015'}

# A secret (in binary form) in SecretsManager that stores the UBL certificates in a .zip file.
self.ubl_certificate_secret_arn: str =\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from aws_rfdk import (
HealthMonitor,
SessionManagerHelper,
)
from aws_rfdk.deadline import (
InstanceUserDataProvider,
Expand Down Expand Up @@ -117,6 +118,12 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ComputeTierProps,
user_data_provider=UserDataProvider(self, 'UserDataProvider')
)

# This is an example of how you can set up a fleet to be enabled for use with the Session
# Manager from the AWS Console. After the fleet deploys, you should be able to go into the
# EC2 Instances Console, right click on your worker instance, select "Connect", and then
# select the Session Manager and open a shell session in the browser.
SessionManagerHelper.grant_permissions_to(self.worker_fleet);

if props.usage_based_licensing and props.licenses:
props.usage_based_licensing.grant_port_access(self.worker_fleet, props.licenses)

Expand Down
10 changes: 9 additions & 1 deletion examples/deadline/All-In-AWS-Infrastructure-Basic/ts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,16 @@ These instructions assume that your working directory is `examples/deadline/All-
```
yarn install
```
3. Change the value in the `deadlineClientLinuxAmiMap` variable in `bin/config.ts` to include the region + AMI ID mapping of your EC2 AMI(s) with Deadline Worker.
3. Change the value in the `deadlineClientLinuxAmiMap` variable in `bin/config.ts` to include the region + AMI ID mapping of your EC2 AMI(s) with Deadline Worker. You can use the following AWS CLI query to find AMI ID's:
```
aws --region <region> ec2 describe-images \
--owners 357466774442 \
--filters "Name=name,Values=*Worker*" "Name=name,Values=*<version>*" \
--query 'Images[*].[ImageId, Name]' \
--output text
```

And enter it into this section of `bin/config.ts`:
```ts
// For example, in the us-west-2 region
public readonly deadlineClientLinuxAmiMap: Record<string, string> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { MongoDbSsplLicenseAcceptance } from 'aws-rfdk';
class AppConfig {

/**
* A map of regions to Deadline Client Linux AMIs. As an example, the Linux Deadline 10.1.11.5 AMI ID from us-west-2
* A map of regions to Deadline Client Linux AMIs. As an example, the Linux Deadline 10.1.12.1 AMI ID from us-west-2
* is filled in. It can be used as-is, added to, or replaced. Ideally the version here should match the one in
* package.json used for staging the render queue and usage based licensing recipes.
*/
public readonly deadlineClientLinuxAmiMap: Record<string, string> = {['us-west-2']: 'ami-0b12631d34ca9939f'};
public readonly deadlineClientLinuxAmiMap: Record<string, string> = {['us-west-2']: 'ami-039f0c1faba28b015'};

/**
* (Optional) A secret (in binary form) in SecretsManager that stores the UBL certificates in a .zip file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import * as cdk from '@aws-cdk/core';
import {
IHost,
InstanceUserDataProvider,
InstanceUserDataProvider,
IRenderQueue,
IWorkerFleet,
UsageBasedLicense,
Expand All @@ -22,6 +22,7 @@ import {
import {
HealthMonitor,
IHealthMonitor,
SessionManagerHelper,
} from 'aws-rfdk';
import { Asset } from '@aws-cdk/aws-s3-assets';
import * as path from 'path'
Expand Down Expand Up @@ -72,15 +73,15 @@ class UserDataProvider extends InstanceUserDataProvider {
}
preRenderQueueConfiguration(host: IHost): void {
host.userData.addCommands('echo preRenderQueueConfiguration');
}
}
preWorkerConfiguration(host: IHost): void {
host.userData.addCommands('echo preWorkerConfiguration');
}
postWorkerLaunch(host: IHost): void {
host.userData.addCommands('echo postWorkerLaunch');
if (host.node.scope != undefined) {
const testScript = new Asset(
host.node.scope as cdk.Construct,
host.node.scope as cdk.Construct,
'SampleAsset',
{path: path.join(__dirname, '..', '..', 'scripts', 'configure_worker.sh')},
);
Expand Down Expand Up @@ -119,7 +120,7 @@ export class ComputeTier extends cdk.Stack {
*/
constructor(scope: cdk.Construct, id: string, props: ComputeTierProps) {
super(scope, id, props);

this.healthMonitor = new HealthMonitor(this, 'HealthMonitor', {
vpc: props.vpc,
// TODO - Evaluate deletion protection for your own needs. This is set to false to
Expand All @@ -137,6 +138,12 @@ export class ComputeTier extends cdk.Stack {
userDataProvider: new UserDataProvider(this, 'UserDataProvider'),
});

// This is an example of how you can set up a fleet to be enabled for use with the Session
// Manager from the AWS Console. After the fleet deploys, you should be able to go into the
// EC2 Instances Console, right click on your worker instance, select "Connect", and then
// select the Session Manager and open a shell session in the browser.
SessionManagerHelper.grantPermissionsTo(this.workerFleet);

if (props.usageBasedLicensing && props.licenses) {
props.usageBasedLicensing.grantPortAccess(this.workerFleet, props.licenses);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"app": "bin/app.js"
},
"config": {
"deadline_ver": "10.1.11.5",
"deadline_ver": "10.1.12.1",
"stage_path": "stage"
},
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions packages/aws-rfdk/lib/core/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ export * from './mountable-efs';
export * from './mountable-filesystem';
export { RFDK_VERSION } from './runtime-info';
export * from './script-assets';
export * from './session-manager-helper';
export * from './staticip-server';
export * from './x509-certificate';
34 changes: 34 additions & 0 deletions packages/aws-rfdk/lib/core/lib/session-manager-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import {
IGrantable,
PolicyStatement,
} from '@aws-cdk/aws-iam';

/**
* This is a helper class meant to make it easier to use the AWS Systems Manager Session Manager
* with any EC2 Instances or AutoScalingGroups. Once enabled, the Session Manager can be used to
* connect to an EC2 Instance through the AWS Console and open a shell session in the browser.
* More details about the AWS Systems Manager Session Manager ca be found here:
* https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html
*/
export class SessionManagerHelper {
/**
* Grants the permissions required to enable Session Manager for the provided IGrantable.
*/
public static grantPermissionsTo(grantable: IGrantable): void {
grantable.grantPrincipal.addToPolicy(new PolicyStatement({
actions: [
'ssmmessages:CreateControlChannel',
'ssmmessages:CreateDataChannel',
'ssmmessages:OpenControlChannel',
'ssmmessages:OpenDataChannel',
'ssm:UpdateInstanceInformation',
],
resources: ['*'],
}));
}
}
93 changes: 93 additions & 0 deletions packages/aws-rfdk/lib/core/test/sessions-manager-helper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import {
expect as expectCDK,
haveResourceLike,
} from '@aws-cdk/assert';
import {
AutoScalingGroup,
} from '@aws-cdk/aws-autoscaling';
import {
AmazonLinuxImage,
Instance,
InstanceClass,
InstanceSize,
InstanceType,
Vpc,
} from '@aws-cdk/aws-ec2';
import { CfnElement, Stack } from '@aws-cdk/core';

import { SessionManagerHelper } from '../lib';

let stack: Stack;
let vpc: Vpc;
const instanceType = InstanceType.of(InstanceClass.T3, InstanceSize.MICRO);
const machineImage = new AmazonLinuxImage();

beforeEach(() => {
stack = new Stack();
vpc = new Vpc(stack, 'VPC');
});

test('Grant SSM permissions to Instance', () => {
const instance = new Instance(stack, 'Instance', {
vpc,
instanceType,
machineImage,
});
SessionManagerHelper.grantPermissionsTo(instance);

const instanceRole = stack.getLogicalId(instance.role.node.defaultChild as CfnElement);

expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [
{
Action: [
'ssmmessages:CreateControlChannel',
'ssmmessages:CreateDataChannel',
'ssmmessages:OpenControlChannel',
'ssmmessages:OpenDataChannel',
'ssm:UpdateInstanceInformation',
],
Effect: 'Allow',
Resource: '*',
},
],
},
Roles: [{ Ref: instanceRole }],
}));
});

test('Grant SSM permissions to ASG', () => {
const asg = new AutoScalingGroup(stack, 'ASG', {
vpc,
instanceType,
machineImage,
});
SessionManagerHelper.grantPermissionsTo(asg);

const asgRole = stack.getLogicalId(asg.role.node.defaultChild as CfnElement);

expectCDK(stack).to(haveResourceLike('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [
{
Action: [
'ssmmessages:CreateControlChannel',
'ssmmessages:CreateDataChannel',
'ssmmessages:OpenControlChannel',
'ssmmessages:OpenDataChannel',
'ssm:UpdateInstanceInformation',
],
Effect: 'Allow',
Resource: '*',
},
],
},
Roles: [{ Ref: asgRole }],
}));
});

0 comments on commit 4b3146f

Please sign in to comment.