Skip to content

Commit

Permalink
feat(reposytory): add Secret Management support
Browse files Browse the repository at this point in the history
  • Loading branch information
kozlove-aws committed Jul 29, 2021
1 parent 1e3eb63 commit f62b3a3
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 4 deletions.
62 changes: 62 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import {
import {
Asset,
} from '@aws-cdk/aws-s3-assets';
import {
ISecret,
Secret } from '@aws-cdk/aws-secretsmanager';
import {
Annotations,
Construct,
Expand Down Expand Up @@ -271,6 +274,27 @@ export interface RepositorySecurityGroupsOptions {
readonly installer?: ISecurityGroup;
}

/**
* Settings used by Deadline Secrets Management, a feature introduced in Deadline 10.1.10 for securely managing storage
* and access of Secrets for your render farm.
* More details at:
* https://docs.thinkboxsoftware.com/products/deadline/10.1/1_User%20Manual/manual/secrets-management/deadline-secrets-management.html
* Using Secrets Management requires TLS to be enabled between the RenderQueue and its clients. If this feature is enabled, the
* `externalTLS` on the `RenderQueueTrafficEncryptionProps` interface on the RenderQueue cannot be disabled.
*/
export interface SecretsManagementProps {
/**
* Whether or not to enable the Secrets Management feature.
* @default true
*/
readonly enabled?: boolean;
/**
* A Secret containing the username and password to use for the admin role
* @default: A random username and password will be generated in a Secret and will need to be retrieved from AWS Secrets Manager if it is needed
*/
readonly credentials?: ISecret;
}

/**
* Properties for the Deadline repository
*/
Expand Down Expand Up @@ -387,6 +411,15 @@ export interface RepositoryProps {
* @default Repository settings are not imported.
*/
readonly repositorySettings?: Asset;

/**
* Define the settings used by Deadline Secrets Management, a feature introduced in Deadline 10.1.10 for securely managing storage
* and access of Secrets for your render farm.
* More details at:
* https://docs.thinkboxsoftware.com/products/deadline/10.1/1_User%20Manual/manual/secrets-management/deadline-secrets-management.html
* @default: Secrets Management will be enabled and a username and password will be automatically generated if none are supplied.
*/
readonly secretsManagementSettings?: SecretsManagementProps
}

/**
Expand Down Expand Up @@ -501,6 +534,11 @@ export class Repository extends Construct implements IRepository {
*/
private readonly installerGroup: AutoScalingGroup;

/**
* Deadline Secrets Management settings.
*/
public readonly secretsManagementSettings: SecretsManagementProps

constructor(scope: Construct, id: string, props: RepositoryProps) {
super(scope, id);

Expand All @@ -519,6 +557,23 @@ export class Repository extends Construct implements IRepository {

this.version = props.version;

this.secretsManagementSettings = {
enabled: props.secretsManagementSettings?.enabled ?? true,
credentials: props.secretsManagementSettings?.credentials ??
(props.secretsManagementSettings?.enabled ?? true) ? new Secret(this, 'SecretManagementAdminUser', {
description: 'Admin credentials for Secret Management',
generateSecretString: {
excludeCharacters: '"()$\'', // Exclude characters that might interact with command shells.
excludePunctuation: true,
includeSpace: false,
passwordLength: 24,
requireEachIncludedType: true,
generateStringKey: 'password',
secretStringTemplate: JSON.stringify({ username: 'admin' }),
},
}) : undefined,
};

this.fileSystem = props.fileSystem ?? (() => {
const fs = new EfsFileSystem(this, 'FileSystem', {
vpc: props.vpc,
Expand Down Expand Up @@ -923,6 +978,13 @@ export class Repository extends Construct implements IRepository {
version.linuxFullVersionString(),
];

if (this.secretsManagementSettings.enabled) {
installerArgs.push('true');
installerArgs.push(Stack.of(this).region);
this.secretsManagementSettings.credentials?.grantRead(installerGroup);
installerArgs.push(this.secretsManagementSettings.credentials?.secretArn ?? '');
}

if (settings) {
const repositorySettingsFilePath = installerGroup.userData.addS3DownloadCommand({
bucket: settings.bucket,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@
# $1: s3 path for the deadline repository installer.
# $2: Path where deadline repository needs to be installed.
# $3: Deadline Repository Version being installed.
# $4: (Optional) Deadline Repository settings file to import.
# $4: (Optional) Secret management is enabled.
# $5: (Optional) Region where stacks are deployed.
# $6: (Optional) Secret management admin credentials ARN.
# $7: (Optional) Deadline Repository settings file to import.

# exit when any command fails
set -xeuo pipefail

S3PATH=$1
PREFIX=$2
DEADLINE_REPOSITORY_VERSION=$3
DEADLINE_REPOSITORY_SETTINGS_FILE=${4:-}
SECRET_MANAGEMENT_ENABLED=${4:false}
if [ "$SECRET_MANAGEMENT_ENABLED" == "true" ]; then
AWS_REGION=${5}
SECRET_MANAGEMENT_ARN=${6}
DEADLINE_REPOSITORY_SETTINGS_FILE=${7:-}
else
DEADLINE_REPOSITORY_SETTINGS_FILE=$SECRET_MANAGEMENT_ENABLED
fi
shift;shift;

# check if repository is already installed at the given path
Expand Down Expand Up @@ -82,7 +92,16 @@ if [ ! -z "$DEADLINE_REPOSITORY_SETTINGS_FILE" ]; then
fi
fi

$REPO_INSTALLER --mode unattended --setpermissions false --prefix "$PREFIX" --installmongodb false --backuprepo false ${INSTALLER_DB_ARGS_STRING} $REPOSITORY_SETTINGS_ARG_STRING
$SECRET_MANAGEMENT_ARG=''
if [ "$SECRET_MANAGEMENT_ENABLED" == "true" ]; then
SM_SECRET_VALUE=$(aws secretsmanager get-secret-value --secret-id=$SECRET_MANAGEMENT_ARN --region=$AWS_REGION)
SM_SECRET_STRING=$(jq -r '.SecretString' <<< "$SM_SECRET_VALUE")
SECRET_MANAGEMENT_USER=$(jq -r '.username' <<< "$SM_SECRET_STRING")
SECRET_MANAGEMENT_PASSWORD=$(jq -r '.password' <<< "$SM_SECRET_STRING")
$SECRET_MANAGEMENT_ARG="--installSecretsManagement true --secretsAdminName $SECRET_MANAGEMENT_USER --secretsAdminPassword $SECRET_MANAGEMENT_PASSWORD"
fi

$REPO_INSTALLER --mode unattended --setpermissions false --prefix "$PREFIX" --installmongodb false --backuprepo false ${INSTALLER_DB_ARGS_STRING} $REPOSITORY_SETTINGS_ARG_STRING $SECRET_MANAGEMENT_ARG

set -x

Expand Down
32 changes: 31 additions & 1 deletion packages/aws-rfdk/lib/deadline/test/repository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from '@aws-cdk/aws-efs';
import { Bucket } from '@aws-cdk/aws-s3';
import { Asset } from '@aws-cdk/aws-s3-assets';
import { Secret } from '@aws-cdk/aws-secretsmanager';
import {
App,
CfnElement,
Expand Down Expand Up @@ -1069,7 +1070,7 @@ describe('tagging', () => {
'AWS::EC2::SecurityGroup': 3,
'AWS::DocDB::DBClusterParameterGroup': 1,
'AWS::DocDB::DBSubnetGroup': 1,
'AWS::SecretsManager::Secret': 1,
'AWS::SecretsManager::Secret': 2,
'AWS::DocDB::DBCluster': 1,
'AWS::DocDB::DBInstance': 1,
'AWS::IAM::Role': 1,
Expand Down Expand Up @@ -1224,3 +1225,32 @@ test('imports repository settings', () => {
const installerGroup = repository.node.tryFindChild('Installer') as AutoScalingGroup;
expect(installerGroup.userData.render()).toContain(`aws s3 cp '${repositorySettings.s3ObjectUrl}'`);
});

test('secret manager enabled', () => {
// GIVEN
const credentials = new Secret(stack, 'SM_AdminUser', {
description: 'Admin credentials for Secret Management',
generateSecretString: {
excludeCharacters: '"()$\'', // Exclude characters that might interact with command shells.
excludePunctuation: true,
includeSpace: false,
passwordLength: 24,
requireEachIncludedType: true,
generateStringKey: 'password',
secretStringTemplate: JSON.stringify({ username: 'admin' }),
},
});

// WHEN
const repository = new Repository(stack, 'Repository', {
vpc,
version,
secretsManagementSettings: {
enabled: true,
credentials,
},
});

// THEN
expect(repository.secretsManagementSettings.credentials).toBe(credentials);
});

0 comments on commit f62b3a3

Please sign in to comment.