Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save bombel2/79a2b17f7ea258f47cf332c5589c6cb9 to your computer and use it in GitHub Desktop.

Select an option

Save bombel2/79a2b17f7ea258f47cf332c5589c6cb9 to your computer and use it in GitHub Desktop.

Revisions

  1. @kritro kritro revised this gist May 25, 2021. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion infra-cdk-app-mysql-stack.ts
    Original file line number Diff line number Diff line change
    @@ -274,7 +274,7 @@ export class InfraCdkappMysqlStack extends cdk.Stack {
    ec2.InitCommand.shellCommand('powershell.exe -File C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeDisks.ps1', { key: "8-Initialize", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    // ec2.InitCommand.shellCommand('msiexec /q /log c:\\cfn\\log\\mysql-install.log /i "C:\\cfn\\mysql.msi"', { key: "91-installMysql", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(30)) }),
    ec2.InitCommand.shellCommand('powershell.exe choco install mysql -y', { key: "9-installMysql", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(30)) }),
    ec2.InitCommand.shellCommand('cfn-signal.exe -e %ERRORLEVEL% --resource mysqlinstance --stack ' + this.stackId + ' --region ' + this.region, { key: "91-Signal", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) })
    ec2.InitCommand.shellCommand('cfn-signal.exe -e %ERRORLEVEL% --resource appmysqlserver --stack ' + this.stackId + ' --region ' + this.region, { key: "91-Signal", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) })
    )

    //create a boolean variable to be able to deploy and undeploy the instance for troubleshooting purposes
    @@ -310,6 +310,9 @@ export class InfraCdkappMysqlStack extends cdk.Stack {

    //allow for the volume to be attached to the instance
    dVolume.grantAttachVolume(instance);

    //override the logicalid
    instance.instance.overrideLogicalId('appmysqlserver');

    //apply tags to the volume
    cdk.Tags.of(instance).add("Name", servername);
  2. @kritro kritro revised this gist May 25, 2021. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions infra-cdk-app-mysql-stack.ts
    Original file line number Diff line number Diff line change
    @@ -259,22 +259,22 @@ export class InfraCdkappMysqlStack extends cdk.Stack {
    //define the initData that will be used when creating the instance, this describes all the commands that will be ran on the instance
    const initData = ec2.CloudFormationInit.fromElements(
    // ec2.InitFile.fromUrl("c:\\cfn\\mysql.msi", "https://downloads.mysql.com/archives/get/p/25/file/mysql-installer-community-8.0.24.0.msi"),
    ec2.InitFile.fromAsset("c:\\cfn\\ContabBootstrapScript.ps1", "./ContabBootstrapScript.ps1"),
    ec2.InitFile.fromAsset("c:\\cfn\\BootstrapScript.ps1", "./BootstrapScript.ps1"),
    ec2.InitFile.fromAsset("c:\\cfn\\CreateADGroups.ps1", "./CreateADGroups.ps1"),
    ec2.InitPackage.msi("https://s3.amazonaws.com/aws-cli/AWSCLI64.msi"),
    ec2.InitCommand.shellCommand('powershell.exe [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString(\'https://chocolatey.org/install.ps1\'))', { key: "1-InstallChoco", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand("powershell.exe -Command Rename-Computer (Get-EC2Tag -Filter @{Name='resource-id'; Values=(Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content}).Where({$_.Key -eq 'Name'}).Value", { key: "2-RenameComputer", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Restart-Service AmazonSSMAgent"', { key: "3-RestartSSMAgent", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand('powershell.exe Add-EC2Volume -InstanceId (Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content -VolumeId ' + dVolume.volumeId + ' -Device ' + targetDevice + ' -Region ' + process.env.CDK_DEFAULT_REGION, { key: "4-AttachVolume", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(60)) }),
    ec2.InitCommand.shellCommand('powershell.exe -File "c:\\cfn\\ContabBootstrapScript.ps1"', { key: "5-install", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(10)) }),
    ec2.InitCommand.shellCommand('powershell.exe -File "c:\\cfn\\BootstrapScript.ps1"', { key: "5-install", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(10)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Send-SSMCommand -InstanceId (Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content -DocumentName ' + domainJoinDocument + ' -TimeoutSecond 600 -Region ' + process.env.CDK_DEFAULT_REGION, { key: "6-DomainJoinServer", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(60)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Restart-Computer -force', { key: "6-Restart", waitAfterCompletion: ec2.InitCommandWaitDuration.forever() }),
    // // ec2.InitCommand.shellCommand('powershell.exe -File "c:\\cfn\\CreateADGroups.ps1"', { key: "7-CreateADGroups", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False', { key: "7-DisableFirewall", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(10)) }),
    ec2.InitCommand.shellCommand('powershell.exe -File C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeDisks.ps1', { key: "8-Initialize", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    // ec2.InitCommand.shellCommand('msiexec /q /log c:\\cfn\\log\\mysql-install.log /i "C:\\cfn\\mysql.msi"', { key: "91-installMysql", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(30)) }),
    ec2.InitCommand.shellCommand('powershell.exe choco install mysql -y', { key: "9-installMysql", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(30)) }),
    ec2.InitCommand.shellCommand('cfn-signal.exe -e %ERRORLEVEL% --resource contabmysqlinstance --stack ' + this.stackId + ' --region ' + this.region, { key: "91-Signal", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) })
    ec2.InitCommand.shellCommand('cfn-signal.exe -e %ERRORLEVEL% --resource mysqlinstance --stack ' + this.stackId + ' --region ' + this.region, { key: "91-Signal", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) })
    )

    //create a boolean variable to be able to deploy and undeploy the instance for troubleshooting purposes
  3. @kritro kritro created this gist May 20, 2021.
    366 changes: 366 additions & 0 deletions infra-cdk-app-mysql-stack.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,366 @@
    import * as cdk from '@aws-cdk/core';
    import * as ec2 from '@aws-cdk/aws-ec2'; // import ec2 library
    import * as iam from '@aws-cdk/aws-iam';
    import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2';
    import * as elbvtargets from '@aws-cdk/aws-elasticloadbalancingv2-targets';
    import * as ssm from '@aws-cdk/aws-ssm';
    import * as kms from '@aws-cdk/aws-kms';


    export class InfraCdkappMysqlStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);


    //Variables
    const volumeEncryptionKey = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/VolumeKmsKeyId');
    var servername = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/servername');
    const environment = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/environment');
    const serverkey = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/serverkey');
    const serverdescription = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/serverdescription');
    var instancetypeparam = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/instancetype');
    const domainJoinDocument = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/domainJoinDocument');
    const directoryID = ssm.StringParameter.valueForStringParameter(this, '/acme/cdk/ec2/app-mysql/directoryId');

    var volumeDsize = 100;
    var volumeCsize = 50;
    const application = "appMysql";
    const createdBy = "[email protected]";
    const os = "Windows";
    const legalEntitiy = "Acme AS";
    const country = "Country";



    //Set default value to be t3.medium
    var instancetype = ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.MEDIUM
    );
    //Check the instancetypeparam from ssm param store and change the instance type accordingly
    if (instancetypeparam == "m5.large") {
    instancetype = ec2.InstanceType.of(
    ec2.InstanceClass.M5,
    ec2.InstanceSize.LARGE
    )
    }

    //Create vpc object
    const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
    vpcName: 'acme-standard-vpc'
    });

    // var subnet1Id = cdk.Fn.importValue('acme-standard-vpc-private-sn-1');
    var subnet1Id = "subnet-1237385573857398";
    const subnet = vpc.selectSubnets({
    subnets: [
    ec2.Subnet.fromSubnetAttributes(this, 'subnet1', {
    subnetId: subnet1Id,
    availabilityZone: 'eu-west-1a'
    })
    ]
    });


    var publicSubnet1Id = "subnet-98765432123456";

    const publicSubnet = vpc.selectSubnets({
    subnets: [
    ec2.Subnet.fromSubnetAttributes(this, 'publicSubnet1', {
    subnetId: publicSubnet1Id,
    availabilityZone: 'eu-west-1a'
    })
    ]
    });



    //Network load balancer
    const nlb = new elbv2.NetworkLoadBalancer(this, 'NLB', {
    vpc,
    internetFacing: true,
    vpcSubnets: publicSubnet,
    loadBalancerName: "app-mysql-nlb",
    crossZoneEnabled: false
    });

    cdk.Tags.of(nlb).add("Name", servername + "-network-load-balancer");
    cdk.Tags.of(nlb).add("Application", application);
    cdk.Tags.of(nlb).add("Description", "network-load-balancer-for-" + serverdescription);



    const role = new iam.Role(this, 'app-mysql-server-role', {
    assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')
    });


    role.addManagedPolicy(iam.ManagedPolicy.fromManagedPolicyArn(this, "AmazonSSMAutomationRole", "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole"));
    role.addManagedPolicy(iam.ManagedPolicy.fromManagedPolicyArn(this, "AmazonSSMManagedInstanceCore", "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"));


    const appPolicy = {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "appIamInstancePolicy",
    "Effect": "Allow",
    "Action": [
    "ec2:DescribeInstances",
    "ssm:ListTagsForResource",
    "ds:CreateComputer"
    ],
    "Resource": "*"
    },
    {
    "Sid": "AttachVolume",
    "Effect": "Allow",
    "Action": [
    "ec2:AttachVolume"
    ],
    "Resource": "*"
    },
    {
    "Sid": "AssumeKMSRole",
    "Effect": "Allow",
    "Action": [
    "sts:AssumeRole"
    ],
    "Resource": "arn:aws:iam::2222222222222:role/*"
    },
    {
    "Sid": "GetKMSKey",
    "Effect": "Allow",
    "Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:ReEncrypt*",
    "kms:GenerateDataKey*",
    "kms:DescribeKey",
    "kms:*"
    ],
    "Resource": "*"
    },
    {
    "Sid": "GetSecretValue",
    "Effect": "Allow",
    "Action": "secretsmanager:GetSecretValue",
    "Resource": [
    "arn:aws:secretsmanager:eu-west-1:111111111111:secret:domainJoinUserAD-test",
    "arn:aws:secretsmanager:eu-west-1:333333333333:secret:domainJoinUserAD-stage",
    "arn:aws:secretsmanager:eu-west-1:666666666666:secret:domainJoinUserAD-prod",
    "arn:aws:secretsmanager:eu-west-1:111111111111:secret:DefaultPasswordForWindowsServer-test",
    "arn:aws:secretsmanager:eu-west-1:333333333333:secret:DefaultPasswordForWindowsServer-stage",
    "arn:aws:secretsmanager:eu-west-1:444444444444:secret:DefaultPasswordForWindowsServer-prod"
    ]
    },
    {
    "Sid": "DomainJoinComputer",
    "Effect": "Allow",
    "Action": [
    "ds:CreateComputer"
    ],
    "Resource": [
    "arn:aws:ds:eu-west-1:" + process.env.account + ":directory/" + directoryID
    ],

    }
    ]
    };

    const appPolicyDocument = iam.PolicyDocument.fromJson(appPolicy);
    var appInstancePolicy = new iam.Policy(this, 'app-instance-policy', {
    policyName: "appIamInstancePolicy",
    document: appPolicyDocument
    });
    appInstancePolicy.attachToRole(role);


    // lets create a security group for our instance
    // A security group acts as a virtual firewall for your instance to control inbound and outbound traffic.
    const securityGroup = new ec2.SecurityGroup(this, 'app-mysql-server-sg',
    {
    vpc: vpc,
    allowAllOutbound: true, // will let your instance send outboud traffic
    securityGroupName: 'app-mysql-server-sg',
    }
    )

    cdk.Tags.of(securityGroup).add("Name", servername + "-security-group");
    cdk.Tags.of(securityGroup).add("Application", application);
    cdk.Tags.of(securityGroup).add("Description", "security-group-for-" + serverdescription);


    // lets use the security group to allow inbound traffic on specific ports from different sources

    //allow mysql from a larger subnet cidr
    securityGroup.addIngressRule(
    ec2.Peer.ipv4("172.10.0.0/20"),
    ec2.Port.tcp(3306),
    'Allows mysql access from AWSCIDR'
    )

    //allow rdp from specific ip, for instance jumpbox
    securityGroup.addIngressRule(
    ec2.Peer.ipv4("172.10.0.55/32"),
    ec2.Port.tcp(3389),
    'Allows rdp access from jumpbox based on ip'
    )

    //allow rdp from another instance based on its security group id
    securityGroup.addIngressRule(ec2.SecurityGroup.fromSecurityGroupId(this, "jumpboxSG", "sg-12345678987654"), ec2.Port.tcp(3389), 'allow rdp access based on the jumpboxs security group id');

    //get the public ip of the actuall machine you are doing this deployment from and allow rdp and mysql from that using the public-ip packet
    const publicIp = require('public-ip');
    async function waitForIP() {
    var ip = await publicIp.v4();
    // console.log(ip);
    return ip;
    }
    function setLaptopIngressRule() {
    waitForIP().then(result => securityGroup.addIngressRule(ec2.Peer.ipv4(result+"/32"), ec2.Port.tcp(3389), 'Allows rdp access from laptop public'));
    }
    function setLaptopIngressRuleMysql() {
    waitForIP().then(result => securityGroup.addIngressRule(ec2.Peer.ipv4(result+"/32"), ec2.Port.tcp(3306), 'Allows mysql access from laptop public'));
    }
    //initialize the functions that creates the ingress rules
    setLaptopIngressRule();
    setLaptopIngressRuleMysql();

    //Get the correct ami from your region for the Windows 2019 base server and put the region and ami id here
    const windows = ec2.MachineImage.latestWindows(ec2.WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE);
    const genericWindows = ec2.MachineImage.genericWindows({
    'eu-west-1': 'ami-87776hhg65f5'
    });

    //define encrypted volume that would be used as D drive
    const dVolume = new ec2.Volume(this, 'DataDisk', {
    availabilityZone: 'eu-west-1a',
    size: cdk.Size.gibibytes(volumeDsize),
    encrypted: true,
    volumeType: ec2.EbsDeviceVolumeType.GP3,
    encryptionKey: kms.Key.fromKeyArn(this, 'VolumeEncryptionKey', volumeEncryptionKey),
    });

    //apply tags to the volume
    cdk.Tags.of(dVolume).add("Name", servername + "-d-volume");
    cdk.Tags.of(dVolume).add("Application", application);
    cdk.Tags.of(dVolume).add("Description", "d-volume-for-" + serverdescription);
    cdk.Tags.of(dVolume).add("CreatedBy", createdBy);

    //if extra custom userdata is needed set them here and uncommend the userdata on the instance
    const userdataScript = "<persist>true</persist>";
    const userData = ec2.UserData.forWindows();
    userData.addCommands(userdataScript);

    //set device name for the volume that would be used as D drive
    const targetDevice = '/dev/sdb';

    //define the initData that will be used when creating the instance, this describes all the commands that will be ran on the instance
    const initData = ec2.CloudFormationInit.fromElements(
    // ec2.InitFile.fromUrl("c:\\cfn\\mysql.msi", "https://downloads.mysql.com/archives/get/p/25/file/mysql-installer-community-8.0.24.0.msi"),
    ec2.InitFile.fromAsset("c:\\cfn\\ContabBootstrapScript.ps1", "./ContabBootstrapScript.ps1"),
    ec2.InitFile.fromAsset("c:\\cfn\\CreateADGroups.ps1", "./CreateADGroups.ps1"),
    ec2.InitPackage.msi("https://s3.amazonaws.com/aws-cli/AWSCLI64.msi"),
    ec2.InitCommand.shellCommand('powershell.exe [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString(\'https://chocolatey.org/install.ps1\'))', { key: "1-InstallChoco", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand("powershell.exe -Command Rename-Computer (Get-EC2Tag -Filter @{Name='resource-id'; Values=(Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content}).Where({$_.Key -eq 'Name'}).Value", { key: "2-RenameComputer", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Restart-Service AmazonSSMAgent"', { key: "3-RestartSSMAgent", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand('powershell.exe Add-EC2Volume -InstanceId (Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content -VolumeId ' + dVolume.volumeId + ' -Device ' + targetDevice + ' -Region ' + process.env.CDK_DEFAULT_REGION, { key: "4-AttachVolume", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(60)) }),
    ec2.InitCommand.shellCommand('powershell.exe -File "c:\\cfn\\ContabBootstrapScript.ps1"', { key: "5-install", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(10)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Send-SSMCommand -InstanceId (Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content -DocumentName ' + domainJoinDocument + ' -TimeoutSecond 600 -Region ' + process.env.CDK_DEFAULT_REGION, { key: "6-DomainJoinServer", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(60)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Restart-Computer -force', { key: "6-Restart", waitAfterCompletion: ec2.InitCommandWaitDuration.forever() }),
    // // ec2.InitCommand.shellCommand('powershell.exe -File "c:\\cfn\\CreateADGroups.ps1"', { key: "7-CreateADGroups", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    ec2.InitCommand.shellCommand('powershell.exe -Command Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False', { key: "7-DisableFirewall", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(10)) }),
    ec2.InitCommand.shellCommand('powershell.exe -File C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeDisks.ps1', { key: "8-Initialize", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) }),
    // ec2.InitCommand.shellCommand('msiexec /q /log c:\\cfn\\log\\mysql-install.log /i "C:\\cfn\\mysql.msi"', { key: "91-installMysql", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(30)) }),
    ec2.InitCommand.shellCommand('powershell.exe choco install mysql -y', { key: "9-installMysql", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(30)) }),
    ec2.InitCommand.shellCommand('cfn-signal.exe -e %ERRORLEVEL% --resource contabmysqlinstance --stack ' + this.stackId + ' --region ' + this.region, { key: "91-Signal", waitAfterCompletion: ec2.InitCommandWaitDuration.of(cdk.Duration.seconds(5)) })
    )

    //create a boolean variable to be able to deploy and undeploy the instance for troubleshooting purposes
    var deployInstance = false;
    var instance: ec2.Instance;

    if (deployInstance) {
    // Finally lets provision our ec2 instance
    instance = new ec2.Instance(this, "app-mysql-server-instance", {
    vpc: vpc,
    role: role,
    securityGroup: securityGroup,
    instanceName: servername,
    instanceType: instancetype,
    blockDevices: [
    {
    deviceName: '/dev/sda1',
    volume: ec2.BlockDeviceVolume.ebs(volumeCsize),
    }
    ],
    machineImage: genericWindows,
    vpcSubnets: subnet,
    // userData: userData, //userdata is in this case not passed along as we dont need the persist tag since cfn-signal is done via init command
    // privateIpAddress: privateIp,
    init: initData,
    initOptions: {
    timeout: cdk.Duration.minutes(35),
    ignoreFailures: false,

    },
    keyName: serverkey, // we will create this in the console before we deploy
    })

    //allow for the volume to be attached to the instance
    dVolume.grantAttachVolume(instance);

    //apply tags to the volume
    cdk.Tags.of(instance).add("Name", servername);
    cdk.Tags.of(instance).add("Application", application);
    cdk.Tags.of(instance).add("Description", serverdescription);
    cdk.Tags.of(instance).add("CreatedBy", createdBy);
    cdk.Tags.of(instance).add("Environment", environment);
    cdk.Tags.of(instance).add("OS", os);
    cdk.Tags.of(instance).add("Country", country);
    cdk.Tags.of(instance).add("Legal Entity", legalEntitiy);
    // cdk.Tags.of(instance).add("", );

    // Add a listener on a mysql port.
    const listener = nlb.addListener('Listener', {
    port: 3306,
    protocol: elbv2.Protocol.TCP
    });
    //apply tags to the listender
    cdk.Tags.of(listener).add("Name", servername + "-mysql-listener");
    cdk.Tags.of(listener).add("Application", application);
    cdk.Tags.of(listener).add("Description", "listener-for-" + serverdescription);

    //add target to the listender, the target is the instance on the mysql port
    listener.addTargets('app-instance-mysql-target', {
    port: 3306,
    targets: [new elbvtargets.InstanceIdTarget(instance.instanceId)]
    })

    //add a listener on the rdp port
    const rdpListener = nlb.addListener('RDP-listender', {
    port: 3389,
    protocol: elbv2.Protocol.TCP
    });
    //apply tags to the listener
    cdk.Tags.of(rdpListener).add("Name", servername + "-rdp-listener");
    cdk.Tags.of(rdpListener).add("Application", application);
    cdk.Tags.of(rdpListener).add("Description", "listener-for-" + serverdescription);

    //add rdp target to the listener, the target is the instance on the rdp port
    rdpListener.addTargets('app-instance-rdp-target', {
    port: 3389,
    targets: [new elbvtargets.InstanceIdTarget(instance.instanceId)]
    })

    new cdk.CfnOutput(this, 'app-nlb-dns-name', {
    value: nlb.loadBalancerDnsName
    })

    new cdk.CfnOutput(this, 'app-mysql-private-ip', {
    value: instance.instancePrivateIp
    })
    }//end if deployInstance
    }
    }