Skip to content

Commit e571cf2

Browse files
authored
Launch templates (#1156)
* 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
1 parent 141d854 commit e571cf2

File tree

8 files changed

+284
-20
lines changed

8 files changed

+284
-20
lines changed

reference-artifacts/SAMPLE_CONFIGS/config.example-oldIP.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@
629629
"name": "EC2-INSTANCE-PROFILE",
630630
"type": "custom",
631631
"resource-types": ["AWS::EC2::Instance"],
632-
"runtime": "nodejs14.x",
632+
"runtime": "nodejs16.x",
633633
"remediation-action": "Attach-IAM-Instance-Profile",
634634
"remediation": true,
635635
"remediation-params": {
@@ -641,7 +641,7 @@
641641
"name": "EC2-INSTANCE-PROFILE-PERMISSIONS",
642642
"type": "custom",
643643
"resource-types": ["AWS::IAM::Role"],
644-
"runtime": "nodejs14.x",
644+
"runtime": "nodejs16.x",
645645
"parameters": {
646646
"AWSManagedPolicies": "AmazonSSMManagedInstanceCore, AmazonSSMDirectoryServiceAccess, CloudWatchAgentServerPolicy",
647647
"CustomerManagedPolicies": "${SEA::EC2InstaceProfilePermissions}",

src/deployments/cdk/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ from secrets manager in your master account.
108108
},
109109
]
110110

111-
112111
Now that we have created all the files, we can start testing the deployment.
113112

114113
Run the following command to synthesize the CloudFormation template from CDK.

src/deployments/cdk/cdk.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
export CONFIG_MODE="development"
44
export CDK_PLUGIN_ASSUME_ROLE_NAME="ASEA-PipelineRole"
5-
export AWS_REGION="us-east-1"
5+
export AWS_REGION="ca-central-1"
66

77
pnpx ts-node --transpile-only cdk.ts $@

src/deployments/cdk/src/common/ad-users-groups.ts

Lines changed: 199 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,40 @@ export class ADUsersAndGroups extends Construct {
123123

124124
const stack = AcceleratorStack.of(this);
125125
const prefix = trimSpecialCharacters(stack.acceleratorPrefix);
126+
const launchTemplate = new cdk.aws_ec2.CfnLaunchTemplate(this, 'RDGWLaunchTemplate', {
127+
launchTemplateName: `${prefix}-RDGWLaunchTemplate`,
128+
launchTemplateData: {
129+
blockDeviceMappings: [
130+
{
131+
deviceName: '/dev/sda1',
132+
ebs: {
133+
volumeSize: 50,
134+
volumeType: 'gp2',
135+
encrypted: true,
136+
},
137+
},
138+
],
139+
// securityGroupIds: [securityGroup.securityGroups[0].id],
140+
imageId: latestRdgwAmiId,
141+
iamInstanceProfile: {
142+
name: createIamInstanceProfileName(madDeploymentConfig['rdgw-instance-role']),
143+
},
144+
networkInterfaces: [
145+
{
146+
deviceIndex: 0,
147+
associatePublicIpAddress: false,
148+
149+
groups: [securityGroup.securityGroups[0].id],
150+
},
151+
],
152+
instanceType: madDeploymentConfig['rdgw-instance-type'],
153+
keyName: keyPairName,
154+
metadataOptions: {
155+
httpTokens: 'required',
156+
httpEndpoint: 'enabled',
157+
},
158+
},
159+
});
126160

127161
const launchConfig = new LaunchConfiguration(this, 'RDGWLaunchConfiguration', {
128162
launchConfigurationName: `${prefix}-RDGWLaunchConfiguration`,
@@ -150,7 +184,11 @@ export class ADUsersAndGroups extends Construct {
150184
const autoScalingGroupSize = madDeploymentConfig['num-rdgw-hosts'];
151185
const autoscalingGroup = new CfnAutoScalingGroup(this, 'RDGWAutoScalingGroupB', {
152186
autoScalingGroupName: `${prefix}-RDGWAutoScalingGroup`,
153-
launchConfigurationName: launchConfig.ref,
187+
// launchConfigurationName: launchConfig.ref,
188+
launchTemplate: {
189+
version: '1',
190+
launchTemplateId: launchTemplate.ref,
191+
},
154192
vpcZoneIdentifier: subnetIds,
155193
maxInstanceLifetime: madDeploymentConfig['rdgw-max-instance-age'] * 86400,
156194
minSize: `${madDeploymentConfig['min-rdgw-hosts']}`,
@@ -174,6 +212,166 @@ export class ADUsersAndGroups extends Construct {
174212
},
175213
};
176214

215+
launchTemplate.addPropertyOverride(
216+
'LaunchTemplateData.UserData',
217+
cdk.Fn.base64(
218+
`<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`,
219+
),
220+
);
221+
222+
launchTemplate.addOverride('Metadata.AWS::CloudFormation::Init', {
223+
configSets: {
224+
config: ['setup', 'join', 'installRDS', 'createADConnectorUser', 'configurePasswordPolicy', 'finalize'],
225+
},
226+
setup: {
227+
files: {
228+
'c:\\cfn\\cfn-hup.conf': {
229+
content: `[main]\n stack=${stackName}\n region=${cdk.Aws.REGION}\n`,
230+
},
231+
'c:\\cfn\\hooks.d\\cfn-auto-reloader.conf': {
232+
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`,
233+
},
234+
'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\AWSQuickStart\\AWSQuickStart.psm1': {
235+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AWSQuickStart.psm1`,
236+
authentication: 'S3AccessCreds',
237+
},
238+
'C:\\cfn\\scripts\\Join-Domain.ps1': {
239+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}Join-Domain.ps1`,
240+
authentication: 'S3AccessCreds',
241+
},
242+
'c:\\cfn\\scripts\\Initialize-RDGW.ps1': {
243+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}Initialize-RDGW.ps1`,
244+
authentication: 'S3AccessCreds',
245+
},
246+
'c:\\cfn\\scripts\\AD-user-setup.ps1': {
247+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-user-setup.ps1`,
248+
authentication: 'S3AccessCreds',
249+
},
250+
'c:\\cfn\\scripts\\AD-group-setup.ps1': {
251+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-group-setup.ps1`,
252+
authentication: 'S3AccessCreds',
253+
},
254+
'c:\\cfn\\scripts\\AD-user-group-setup.ps1': {
255+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-user-group-setup.ps1`,
256+
authentication: 'S3AccessCreds',
257+
},
258+
'c:\\cfn\\scripts\\AD-group-grant-permissions-setup.ps1': {
259+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-group-grant-permissions-setup.ps1`,
260+
authentication: 'S3AccessCreds',
261+
},
262+
'c:\\cfn\\scripts\\AD-connector-permissions-setup.ps1': {
263+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}AD-connector-permissions-setup.ps1`,
264+
authentication: 'S3AccessCreds',
265+
},
266+
'c:\\cfn\\scripts\\Configure-password-policy.ps1': {
267+
source: `https://${s3BucketName}.s3.${cdk.Aws.REGION}.amazonaws.com/${s3KeyPrefix}Configure-password-policy.ps1`,
268+
authentication: 'S3AccessCreds',
269+
},
270+
},
271+
services: {
272+
windows: {
273+
'cfn-hup': {
274+
enabled: 'true',
275+
ensureRunning: 'true',
276+
files: ['c:\\cfn\\cfn-hup.conf', 'c:\\cfn\\hooks.d\\cfn-auto-reloader.conf'],
277+
},
278+
},
279+
},
280+
commands: {
281+
'a-set-execution-policy': {
282+
command: 'powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force"',
283+
waitAfterCompletion: '0',
284+
},
285+
'b-init-quickstart-module': {
286+
command: `powershell.exe -Command "New-AWSQuickStartResourceSignal -Stack ${props.stackName} -Resource ${autoscalingGroup.logicalId} -Region ${cdk.Aws.REGION}"`,
287+
waitAfterCompletion: '0',
288+
},
289+
},
290+
},
291+
join: {
292+
commands: {
293+
'a-join-domain': {
294+
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)"`,
295+
waitAfterCompletion: 'forever',
296+
},
297+
},
298+
},
299+
installRDS: {
300+
commands: {
301+
'a-install-rds': {
302+
command: 'powershell.exe -Command "Install-WindowsFeature RDS-Gateway,RSAT-RDS-Gateway,RSAT-AD-Tools"',
303+
waitAfterCompletion: '0',
304+
},
305+
'b-configure-rdgw': {
306+
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\Initialize-RDGW.ps1 -ServerFQDN $($env:COMPUTERNAME + '.${madDeploymentConfig['dns-domain']}') -DomainNetBiosName ${madDeploymentConfig['netbios-domain']} -GroupName 'domain admins'`,
307+
waitAfterCompletion: '0',
308+
},
309+
},
310+
},
311+
createADConnectorUser: {
312+
commands: {
313+
'a-create-ad-users': {
314+
command: `powershell.exe -ExecutionPolicy RemoteSigned ${adUsersCommand.join('; ')}`,
315+
waitAfterCompletion: '0',
316+
},
317+
'b-create-ad-groups': {
318+
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\AD-group-setup.ps1 -GroupNames \'${adGroups.join(
319+
',',
320+
)}\' -DomainAdminUser ${
321+
madDeploymentConfig['netbios-domain']
322+
}\\admin -DomainAdminPassword ((Get-SECSecretValue -SecretId ${adminPasswordArn}).SecretString)`,
323+
waitAfterCompletion: '0',
324+
},
325+
'c-configure-ad-users-groups': {
326+
command: `powershell.exe -ExecutionPolicy RemoteSigned ${adUserGroupsCommand.join('; ')}`,
327+
waitAfterCompletion: '0',
328+
},
329+
'd-configure-ad-group-permissions': {
330+
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)`,
331+
waitAfterCompletion: '0',
332+
},
333+
},
334+
},
335+
configurePasswordPolicy: {
336+
commands: {
337+
'a-set-password-policy': {
338+
command: `powershell.exe -ExecutionPolicy RemoteSigned C:\\cfn\\scripts\\Configure-password-policy.ps1 -DomainAdminUser admin -DomainAdminPassword ((Get-SECSecretValue -SecretId ${adminPasswordArn}).SecretString) -ComplexityEnabled:$${pascalCase(
339+
String(madDeploymentConfig['password-policies'].complexity),
340+
)} -LockoutDuration 00:${
341+
madDeploymentConfig['password-policies']['lockout-duration']
342+
}:00 -LockoutObservationWindow 00:${
343+
madDeploymentConfig['password-policies']['lockout-attempts-reset']
344+
}:00 -LockoutThreshold ${madDeploymentConfig['password-policies']['failed-attempts']} -MaxPasswordAge:${
345+
madDeploymentConfig['password-policies']['max-age']
346+
}.00:00:00 -MinPasswordAge:${
347+
madDeploymentConfig['password-policies']['min-age']
348+
}.00:00:00 -MinPasswordLength:${
349+
madDeploymentConfig['password-policies']['min-len']
350+
} -PasswordHistoryCount:${madDeploymentConfig['password-policies'].history} -ReversibleEncryptionEnabled:$${
351+
madDeploymentConfig['password-policies'].reversible
352+
}`,
353+
waitAfterCompletion: '0',
354+
},
355+
},
356+
},
357+
finalize: {
358+
commands: {
359+
'1-signal-success': {
360+
command: 'powershell.exe -Command "Write-AWSQuickStartStatus"',
361+
waitAfterCompletion: '0',
362+
},
363+
},
364+
},
365+
});
366+
367+
launchTemplate.addOverride('Metadata.AWS::CloudFormation::Authentication', {
368+
S3AccessCreds: {
369+
type: 'S3',
370+
roleName: madDeploymentConfig['rdgw-instance-role'],
371+
buckets: [s3BucketName],
372+
},
373+
});
374+
177375
launchConfig.addOverride('Metadata.AWS::CloudFormation::Authentication', {
178376
S3AccessCreds: {
179377
type: 'S3',
@@ -185,7 +383,6 @@ export class ADUsersAndGroups extends Construct {
185383
launchConfig.userData = cdk.Fn.base64(
186384
`<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`,
187385
);
188-
189386
launchConfig.addOverride('Metadata.AWS::CloudFormation::Init', {
190387
configSets: {
191388
config: ['setup', 'join', 'installRDS', 'createADConnectorUser', 'configurePasswordPolicy', 'finalize'],

src/deployments/cdk/src/deployments/firewall/cluster/step-3.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export async function step3(props: FirewallStep3Props) {
108108
continue;
109109
}
110110

111-
// TODO add region check also if vpc name is not unique accross Account
111+
// TODO add region check also if vpc name is not unique across Account
112112
const vpcConfig = vpcConfigs.find(v => v.vpcConfig.name === firewallConfig.vpc)?.vpcConfig;
113113
if (!vpcConfig) {
114114
console.log(`Skipping firewall deployment because of missing VPC config "${firewallConfig.vpc}"`);

src/deployments/cdk/src/deployments/firewall/cluster/step-4.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ async function createFirewallCluster(props: {
183183
name: `${firewallName}`,
184184
suffixLength: 0,
185185
});
186+
187+
const launchTemplateName = createName({
188+
name: `${firewallName}lt`,
189+
suffixLength: 0,
190+
});
191+
186192
const blockDeviceMappings = deviceNames.map(deviceName => ({
187193
deviceName,
188194
ebs: {
@@ -192,6 +198,33 @@ async function createFirewallCluster(props: {
192198
},
193199
}));
194200

201+
const launchTemplate = new cdk.aws_ec2.CfnLaunchTemplate(accountStack, `FirewallLaunchTemplate-${firewallName}`, {
202+
launchTemplateName,
203+
launchTemplateData: {
204+
blockDeviceMappings,
205+
// securityGroupIds: [securityGroup.securityGroups[0].id],
206+
imageId,
207+
iamInstanceProfile: {
208+
name: instanceRoleName ? createIamInstanceProfileName(instanceRoleName) : undefined,
209+
},
210+
networkInterfaces: [
211+
{
212+
deviceIndex: 0,
213+
associatePublicIpAddress,
214+
215+
groups: [securityGroup.id],
216+
},
217+
],
218+
instanceType,
219+
keyName,
220+
metadataOptions: {
221+
httpTokens: 'required',
222+
httpEndpoint: 'enabled',
223+
},
224+
userData: userData ? cdk.Fn.base64(userData) : undefined,
225+
},
226+
});
227+
195228
// Create LaunchConfiguration
196229
const launchConfig = new LaunchConfiguration(accountStack, `FirewallLaunchConfiguration-${firewallName}`, {
197230
launchConfigurationName,
@@ -246,7 +279,10 @@ async function createFirewallCluster(props: {
246279
}
247280
const autoScalingGroup = new elb.CfnAutoScalingGroup(accountStack, `Firewall-AutoScalingGroup-${firewallName}`, {
248281
autoScalingGroupName,
249-
launchConfigurationName: launchConfig.ref,
282+
launchTemplate: {
283+
version: '1',
284+
launchTemplateId: launchTemplate.ref,
285+
},
250286
vpcZoneIdentifier: subnetIds,
251287
maxInstanceLifetime: maxInstanceAge * 86400,
252288
minSize: `${minSize}`,

src/deployments/cdk/tsconfig.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,5 @@
1414
"resolveJsonModule": true,
1515
"typeRoots": ["node_modules/@types"]
1616
},
17-
"include": [
18-
"src",
19-
"./tools.ts",
20-
"./toolkit.ts",
21-
"./cdk.ts",
22-
"./microstats.d.ts",
23-
],
17+
"include": ["src", "./tools.ts", "./toolkit.ts", "./cdk.ts", "./microstats.d.ts"]
2418
}

0 commit comments

Comments
 (0)