Skip to content

Commit

Permalink
Launch templates (#1156)
Browse files Browse the repository at this point in the history
* added launch template for rdgw

* fixed lauch templates

* launch templates

* fixed launchtemplate

* Fixed construct name

* Fixed construct name

* Fixed construct name

* Fixed lt versions

* prettier fixes

* fixed prettier errors

* fixed prettier error
  • Loading branch information
hickeydh-aws authored Jun 9, 2023
1 parent 141d854 commit e571cf2
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 20 deletions.
4 changes: 2 additions & 2 deletions reference-artifacts/SAMPLE_CONFIGS/config.example-oldIP.json
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@
"name": "EC2-INSTANCE-PROFILE",
"type": "custom",
"resource-types": ["AWS::EC2::Instance"],
"runtime": "nodejs14.x",
"runtime": "nodejs16.x",
"remediation-action": "Attach-IAM-Instance-Profile",
"remediation": true,
"remediation-params": {
Expand All @@ -641,7 +641,7 @@
"name": "EC2-INSTANCE-PROFILE-PERMISSIONS",
"type": "custom",
"resource-types": ["AWS::IAM::Role"],
"runtime": "nodejs14.x",
"runtime": "nodejs16.x",
"parameters": {
"AWSManagedPolicies": "AmazonSSMManagedInstanceCore, AmazonSSMDirectoryServiceAccess, CloudWatchAgentServerPolicy",
"CustomerManagedPolicies": "${SEA::EC2InstaceProfilePermissions}",
Expand Down
1 change: 0 additions & 1 deletion src/deployments/cdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ from secrets manager in your master account.
},
]


Now that we have created all the files, we can start testing the deployment.

Run the following command to synthesize the CloudFormation template from CDK.
Expand Down
2 changes: 1 addition & 1 deletion src/deployments/cdk/cdk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

export CONFIG_MODE="development"
export CDK_PLUGIN_ASSUME_ROLE_NAME="ASEA-PipelineRole"
export AWS_REGION="us-east-1"
export AWS_REGION="ca-central-1"

pnpx ts-node --transpile-only cdk.ts $@
201 changes: 199 additions & 2 deletions src/deployments/cdk/src/common/ad-users-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,40 @@ export class ADUsersAndGroups extends Construct {

const stack = AcceleratorStack.of(this);
const prefix = trimSpecialCharacters(stack.acceleratorPrefix);
const launchTemplate = new cdk.aws_ec2.CfnLaunchTemplate(this, 'RDGWLaunchTemplate', {
launchTemplateName: `${prefix}-RDGWLaunchTemplate`,
launchTemplateData: {
blockDeviceMappings: [
{
deviceName: '/dev/sda1',
ebs: {
volumeSize: 50,
volumeType: 'gp2',
encrypted: true,
},
},
],
// securityGroupIds: [securityGroup.securityGroups[0].id],
imageId: latestRdgwAmiId,
iamInstanceProfile: {
name: createIamInstanceProfileName(madDeploymentConfig['rdgw-instance-role']),
},
networkInterfaces: [
{
deviceIndex: 0,
associatePublicIpAddress: false,

groups: [securityGroup.securityGroups[0].id],
},
],
instanceType: madDeploymentConfig['rdgw-instance-type'],
keyName: keyPairName,
metadataOptions: {
httpTokens: 'required',
httpEndpoint: 'enabled',
},
},
});

const launchConfig = new LaunchConfiguration(this, 'RDGWLaunchConfiguration', {
launchConfigurationName: `${prefix}-RDGWLaunchConfiguration`,
Expand Down Expand Up @@ -150,7 +184,11 @@ export class ADUsersAndGroups extends Construct {
const autoScalingGroupSize = madDeploymentConfig['num-rdgw-hosts'];
const autoscalingGroup = new CfnAutoScalingGroup(this, 'RDGWAutoScalingGroupB', {
autoScalingGroupName: `${prefix}-RDGWAutoScalingGroup`,
launchConfigurationName: launchConfig.ref,
// launchConfigurationName: launchConfig.ref,
launchTemplate: {
version: '1',
launchTemplateId: launchTemplate.ref,
},
vpcZoneIdentifier: subnetIds,
maxInstanceLifetime: madDeploymentConfig['rdgw-max-instance-age'] * 86400,
minSize: `${madDeploymentConfig['min-rdgw-hosts']}`,
Expand All @@ -174,6 +212,166 @@ export class ADUsersAndGroups extends Construct {
},
};

launchTemplate.addPropertyOverride(
'LaunchTemplateData.UserData',
cdk.Fn.base64(
`<script>\n cfn-init.exe -v -c config -s ${stackId} -r ${launchTemplate.logicalId} --region ${cdk.Aws.REGION} \n # Signal the status from cfn-init\n cfn-signal -e $? --stack ${props.stackName} --resource ${autoscalingGroup.logicalId} --region ${cdk.Aws.REGION}\n </script>\n`,
),
);

launchTemplate.addOverride('Metadata.AWS::CloudFormation::Init', {
configSets: {
config: ['setup', 'join', 'installRDS', 'createADConnectorUser', 'configurePasswordPolicy', 'finalize'],
},
setup: {
files: {
'c:\\cfn\\cfn-hup.conf': {
content: `[main]\n stack=${stackName}\n region=${cdk.Aws.REGION}\n`,
},
'c:\\cfn\\hooks.d\\cfn-auto-reloader.conf': {
content: `[cfn-auto-reloader-hook]\n triggers=post.update\n path=Resources.${launchTemplate.logicalId}.Metadata.AWS::CloudFormation::Init\n action=cfn-init.exe -v -c config -s ${stackId} -r ${launchTemplate.logicalId} --region ${cdk.Aws.REGION}\n`,
},
'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\AWSQuickStart\\AWSQuickStart.psm1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AWSQuickStart.psm1`,
authentication: 'S3AccessCreds',
},
'C:\\cfn\\scripts\\Join-Domain.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}Join-Domain.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\Initialize-RDGW.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}Initialize-RDGW.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\AD-user-setup.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-user-setup.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\AD-group-setup.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-group-setup.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\AD-user-group-setup.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-user-group-setup.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\AD-group-grant-permissions-setup.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-group-grant-permissions-setup.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\AD-connector-permissions-setup.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-connector-permissions-setup.ps1`,
authentication: 'S3AccessCreds',
},
'c:\\cfn\\scripts\\Configure-password-policy.ps1': {
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}Configure-password-policy.ps1`,
authentication: 'S3AccessCreds',
},
},
services: {
windows: {
'cfn-hup': {
enabled: 'true',
ensureRunning: 'true',
files: ['c:\\cfn\\cfn-hup.conf', 'c:\\cfn\\hooks.d\\cfn-auto-reloader.conf'],
},
},
},
commands: {
'a-set-execution-policy': {
command: 'powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force"',
waitAfterCompletion: '0',
},
'b-init-quickstart-module': {
command: `powershell.exe -Command "New-AWSQuickStartResourceSignal -Stack ${props.stackName} -Resource ${autoscalingGroup.logicalId} -Region ${cdk.Aws.REGION}"`,
waitAfterCompletion: '0',
},
},
},
join: {
commands: {
'a-join-domain': {
command: `powershell.exe -Command "C:\\cfn\\scripts\\Join-Domain.ps1 -DomainName ${madDeploymentConfig['dns-domain']} -UserName ${madDeploymentConfig['netbios-domain']}\\admin -Password ((Get-SECSecretValue -SecretId ${adminPasswordArn}).SecretString)"`,
waitAfterCompletion: 'forever',
},
},
},
installRDS: {
commands: {
'a-install-rds': {
command: 'powershell.exe -Command "Install-WindowsFeature RDS-Gateway,RSAT-RDS-Gateway,RSAT-AD-Tools"',
waitAfterCompletion: '0',
},
'b-configure-rdgw': {
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\Initialize-RDGW.ps1 -ServerFQDN $($env:COMPUTERNAME + '.${madDeploymentConfig['dns-domain']}') -DomainNetBiosName ${madDeploymentConfig['netbios-domain']} -GroupName 'domain admins'`,
waitAfterCompletion: '0',
},
},
},
createADConnectorUser: {
commands: {
'a-create-ad-users': {
command: `powershell.exe -ExecutionPolicy RemoteSigned ${adUsersCommand.join('; ')}`,
waitAfterCompletion: '0',
},
'b-create-ad-groups': {
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\AD-group-setup.ps1 -GroupNames \'${adGroups.join(
',',
)}\' -DomainAdminUser ${
madDeploymentConfig['netbios-domain']
}\\admin -DomainAdminPassword ((Get-SECSecretValue -SecretId ${adminPasswordArn}).SecretString)`,
waitAfterCompletion: '0',
},
'c-configure-ad-users-groups': {
command: `powershell.exe -ExecutionPolicy RemoteSigned ${adUserGroupsCommand.join('; ')}`,
waitAfterCompletion: '0',
},
'd-configure-ad-group-permissions': {
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\AD-connector-permissions-setup.ps1 -GroupName ${madDeploymentConfig['adc-group']} -DomainAdminUser ${madDeploymentConfig['netbios-domain']}\\admin -DomainAdminPassword ((Get-SECSecretValue -SecretId ${adminPasswordArn}).SecretString)`,
waitAfterCompletion: '0',
},
},
},
configurePasswordPolicy: {
commands: {
'a-set-password-policy': {
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\Configure-password-policy.ps1 -DomainAdminUser admin -DomainAdminPassword ((Get-SECSecretValue -SecretId ${adminPasswordArn}).SecretString) -ComplexityEnabled:$${pascalCase(
String(madDeploymentConfig['password-policies'].complexity),
)} -LockoutDuration 00:${
madDeploymentConfig['password-policies']['lockout-duration']
}:00 -LockoutObservationWindow 00:${
madDeploymentConfig['password-policies']['lockout-attempts-reset']
}:00 -LockoutThreshold ${madDeploymentConfig['password-policies']['failed-attempts']} -MaxPasswordAge:${
madDeploymentConfig['password-policies']['max-age']
}.00:00:00 -MinPasswordAge:${
madDeploymentConfig['password-policies']['min-age']
}.00:00:00 -MinPasswordLength:${
madDeploymentConfig['password-policies']['min-len']
} -PasswordHistoryCount:${madDeploymentConfig['password-policies'].history} -ReversibleEncryptionEnabled:$${
madDeploymentConfig['password-policies'].reversible
}`,
waitAfterCompletion: '0',
},
},
},
finalize: {
commands: {
'1-signal-success': {
command: 'powershell.exe -Command "Write-AWSQuickStartStatus"',
waitAfterCompletion: '0',
},
},
},
});

launchTemplate.addOverride('Metadata.AWS::CloudFormation::Authentication', {
S3AccessCreds: {
type: 'S3',
roleName: madDeploymentConfig['rdgw-instance-role'],
buckets: [s3BucketName],
},
});

launchConfig.addOverride('Metadata.AWS::CloudFormation::Authentication', {
S3AccessCreds: {
type: 'S3',
Expand All @@ -185,7 +383,6 @@ export class ADUsersAndGroups extends Construct {
launchConfig.userData = cdk.Fn.base64(
`<script>\n cfn-init.exe -v -c config -s ${stackId} -r ${launchConfig.logicalId} --region ${cdk.Aws.REGION} \n # Signal the status from cfn-init\n cfn-signal -e $? --stack ${props.stackName} --resource ${autoscalingGroup.logicalId} --region ${cdk.Aws.REGION}\n </script>\n`,
);

launchConfig.addOverride('Metadata.AWS::CloudFormation::Init', {
configSets: {
config: ['setup', 'join', 'installRDS', 'createADConnectorUser', 'configurePasswordPolicy', 'finalize'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export async function step3(props: FirewallStep3Props) {
continue;
}

// TODO add region check also if vpc name is not unique accross Account
// TODO add region check also if vpc name is not unique across Account
const vpcConfig = vpcConfigs.find(v => v.vpcConfig.name === firewallConfig.vpc)?.vpcConfig;
if (!vpcConfig) {
console.log(`Skipping firewall deployment because of missing VPC config "${firewallConfig.vpc}"`);
Expand Down
38 changes: 37 additions & 1 deletion src/deployments/cdk/src/deployments/firewall/cluster/step-4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ async function createFirewallCluster(props: {
name: `${firewallName}`,
suffixLength: 0,
});

const launchTemplateName = createName({
name: `${firewallName}lt`,
suffixLength: 0,
});

const blockDeviceMappings = deviceNames.map(deviceName => ({
deviceName,
ebs: {
Expand All @@ -192,6 +198,33 @@ async function createFirewallCluster(props: {
},
}));

const launchTemplate = new cdk.aws_ec2.CfnLaunchTemplate(accountStack, `FirewallLaunchTemplate-${firewallName}`, {
launchTemplateName,
launchTemplateData: {
blockDeviceMappings,
// securityGroupIds: [securityGroup.securityGroups[0].id],
imageId,
iamInstanceProfile: {
name: instanceRoleName ? createIamInstanceProfileName(instanceRoleName) : undefined,
},
networkInterfaces: [
{
deviceIndex: 0,
associatePublicIpAddress,

groups: [securityGroup.id],
},
],
instanceType,
keyName,
metadataOptions: {
httpTokens: 'required',
httpEndpoint: 'enabled',
},
userData: userData ? cdk.Fn.base64(userData) : undefined,
},
});

// Create LaunchConfiguration
const launchConfig = new LaunchConfiguration(accountStack, `FirewallLaunchConfiguration-${firewallName}`, {
launchConfigurationName,
Expand Down Expand Up @@ -246,7 +279,10 @@ async function createFirewallCluster(props: {
}
const autoScalingGroup = new elb.CfnAutoScalingGroup(accountStack, `Firewall-AutoScalingGroup-${firewallName}`, {
autoScalingGroupName,
launchConfigurationName: launchConfig.ref,
launchTemplate: {
version: '1',
launchTemplateId: launchTemplate.ref,
},
vpcZoneIdentifier: subnetIds,
maxInstanceLifetime: maxInstanceAge * 86400,
minSize: `${minSize}`,
Expand Down
8 changes: 1 addition & 7 deletions src/deployments/cdk/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,5 @@
"resolveJsonModule": true,
"typeRoots": ["node_modules/@types"]
},
"include": [
"src",
"./tools.ts",
"./toolkit.ts",
"./cdk.ts",
"./microstats.d.ts",
],
"include": ["src", "./tools.ts", "./toolkit.ts", "./cdk.ts", "./microstats.d.ts"]
}
Loading

0 comments on commit e571cf2

Please sign in to comment.