constructor()

in cdk/lib/cdk-stack.ts [13:165]


  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const keyPairName = new cdk.CfnParameter(this, 'keyPairName', {
      type: 'String',
      description: 'The name of the EC2 keypair associated with the Windows Server instance.'
    });

    // Create a VPC. 
    const vpc = new ec2.Vpc(this, 'vpc', {
      cidr: '172.20.0.0/16',
      subnetConfiguration: [
        {
          subnetType: ec2.SubnetType.PUBLIC,
          name: 'Public'
        },
        {
          subnetType: ec2.SubnetType.PRIVATE,
          name: 'Private'
        }
      ]
    });

    // Create an ECS cluster.
    const cluster = new ecs.Cluster(this, 'ecs-cluster', {
      clusterName: 'ecs-kerberos-sample',
      vpc: vpc
    });

    // Set up ECS VPC endpoints.
    let ecsEndpoint = vpc.addInterfaceEndpoint('ecs-endpoint', {
      service: ec2.InterfaceVpcEndpointAwsService.ECS,
      privateDnsEnabled: true // This must be enabled
    });
    cdk.Tag.add(ecsEndpoint, 'Name', 'ecs-kerberos-sample/ecs-endpoint');
    ecsEndpoint.connections.allowDefaultPortFromAnyIpv4('Allow HTTPS traffic');

    let ecsAgentEndpoint = vpc.addInterfaceEndpoint('ecs-agent-endpoint', {
      service: ec2.InterfaceVpcEndpointAwsService.ECS_AGENT,
      privateDnsEnabled: true // This must be enabled
    });
    cdk.Tag.add(ecsAgentEndpoint, 'Name', 'ecs-kerberos-sample/ecs-agent-endpoint');
    ecsAgentEndpoint.connections.allowDefaultPortFromAnyIpv4('Allow HTTPS traffic');

    let ecsTelemetryEndpoint = vpc.addInterfaceEndpoint('ecs-telemetry-endpoint', {
      service: ec2.InterfaceVpcEndpointAwsService.ECS_TELEMETRY,
      privateDnsEnabled: true // This must be enabled
    });
    cdk.Tag.add(ecsTelemetryEndpoint, 'Name', 'ecs-kerberos-sample/ecs-telemetry-endpoint');
    ecsTelemetryEndpoint.connections.allowDefaultPortFromAnyIpv4('Allow HTTPS traffic');


    // Set up VPC endpoints for ECR.
    // See: https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html
    let ecrEndpoint = vpc.addInterfaceEndpoint('ecr-api-endpoint', {
      service: ec2.InterfaceVpcEndpointAwsService.ECR,
      privateDnsEnabled: true // This must be enabled
    });
    cdk.Tag.add(ecrEndpoint, 'Name', 'ecs-kerberos-sample/ecr-api-endpoint');
    ecrEndpoint.connections.allowDefaultPortFromAnyIpv4('Allow HTTPS traffic');

    let ecrDockerEndpoint = vpc.addInterfaceEndpoint('ecr-docker-endpoint', {
      service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
      privateDnsEnabled: true // This must be enabled
    });
    cdk.Tag.add(ecrDockerEndpoint, 'Name', 'ecs-kerberos-sample/ecr-docker-endpoint');
    ecrDockerEndpoint.connections.allowDefaultPortFromAnyIpv4('Allow HTTPS traffic');

    let s3Endpoint = vpc.addGatewayEndpoint('ecr-s3-endpoint', {
      // Services that use ECR also need an S3 endpoint.
      service: ec2.GatewayVpcEndpointAwsService.S3
    });
    cdk.Tag.add(s3Endpoint, 'Name', 'ecs-kerberos-sample/ecr-s3-endpoint');



    // ------------------------------------------------------------------------------------------------------------------
    // Create an AWS Managed Active Directory in the VPC. 
    // NOTE: Typically, the Active Directory will be deployed into another VPC or account. In that case, remove this code 
    // and replace it with code to establish a network route between the VPC created above and the Active Directory.

    // Create a secure password for the Active Directory admin user and store it in Secrets Manager.
    const activeDirectoryAdminPasswordSecret = new secretsmanager.Secret(this, 'active-directory-admin-password-secret',
      {
        secretName: '/ecs-kerberos-sample/active-directory-administrator-password',
        generateSecretString: {
          excludeCharacters: '"\'' // Passwords with quotes are hard to work with on the command line.
        }
      });

    // Output the ARN of the directory admin password secret.
    new cdk.CfnOutput(this, 'ActiveDirectoryAdminPasswordSecretARN', { value: activeDirectoryAdminPasswordSecret.secretArn });

    const activeDirectory = new directory.CfnMicrosoftAD(this, 'directory', {
      name: 'directory.ecs-kerberos-sample.com',
      password: activeDirectoryAdminPasswordSecret.secretValue.toString(),
      edition: 'Standard',
      vpcSettings: {
        vpcId: vpc.vpcId,
        subnetIds: [vpc.publicSubnets[0].subnetId, vpc.publicSubnets[1].subnetId]
      }
    });

    // Deploy a Windows EC2 instance to manage the Active Directory.
    // In a typical deployment, this instance is likely unnecessary.
    const windowsServerImage = ec2.MachineImage.lookup({
      name: 'Windows_Server-2019-English-Full-Base*',
      windows: true
    });
    const directoryManagementInstance = new ec2.Instance(this, 'active-directory-management-instance', {
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: windowsServerImage,
      vpc: vpc,
      vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
      keyName: keyPairName.valueAsString
    });

    // Store the instance's security group ID in the Systems Manager Parameter Store, so it can be referenced by other stacks.
    const windowsServerInstanceSecurityGroupId = new ssm.StringParameter(this, 'active-directory-management-instance-security-group-id', {
      allowedPattern: '.*',
      description: 'ID of the Security Group for the Windows Server instance used to manage the Active Directory',
      parameterName: '/ecs-kerberos-sample/directory-management-server-security-group-id',
      stringValue: directoryManagementInstance.connections.securityGroups[0].securityGroupId,
      tier: ssm.ParameterTier.STANDARD
    });

    // Output the management instance's security group ID so we can modify it to allow connections.
    new cdk.CfnOutput(this, 'DirectoryManagementInstanceSecurityGroupID', { value: directoryManagementInstance.connections.securityGroups[0].securityGroupId });


    // ------------------------------------------------------------------------------------------------------------------


    // These steps are required even if using an existing directory.

    // Store the Active Directory ID in the Systems Manager Parameter Store, so it can be referenced by other stacks.
    const activeDirectoryIdentifierParameter = new ssm.StringParameter(this, 'active-directory-id', {
      allowedPattern: '.*',
      description: 'Active Directory ID',
      parameterName: '/ecs-kerberos-sample/active-directory-id',
      stringValue: activeDirectory.attrAlias,
      tier: ssm.ParameterTier.STANDARD
    });

    // Create a DHCP Options Set so the VPC uses the Active Directory DNS servers.
    const activeDirectoryDhcpOptionsSet = new ec2.CfnDHCPOptions(this, 'directory-dhcp-os', {
      domainNameServers: activeDirectory.attrDnsIpAddresses
    });
    new ec2.CfnVPCDHCPOptionsAssociation(this, 'directory-dhcp-os-association', {
      vpcId: vpc.vpcId,
      dhcpOptionsId: activeDirectoryDhcpOptionsSet.ref
    });
  }