public AdConnectorConstruct()

in WorkingFromHome/ClientConnection/src/main/java/com/ilmlf/clientconnection/AdConnectorConstruct.java [79:253]


  public AdConnectorConstruct(
      software.constructs.@NotNull Construct scope, @NotNull String id, AdConnectorProps props)
      throws IOException {
    super(scope, id);

    /*
      Java CDK custom resources need to be packaged for use
      Packaging instructions are provided here
    */
    List<String> adConnectorCustomResourcePackagingInstructions =
        Arrays.asList(
            "/bin/sh",
            "-c",
            "mvn clean install "
                + "&& cp /asset-input/target/AdConnectorCustomResource.jar /asset-output/");

    /*
      The package builder is configured...
      - using our previous packaging instructions
      - to use a Java 11 run time
    */
    BundlingOptions.Builder builderOptions =
        BundlingOptions.builder()
            .command(adConnectorCustomResourcePackagingInstructions)
            .image(Runtime.JAVA_11.getBundlingImage())
            .user("root")
            .outputType(ARCHIVED);

    /*
      The onEventHandler function makes API calls to create AWS resources
      Here we specify:
      - that our OnEventHandler.java is defined in the ./AdConnectorCustomResource directory
      - that the resulting AWS Lambda function should:
        - have a memory size of 1024 MB
        - time out after 10 seconds
    */
    Function onEventHandler =
        new Function(
            this,
            "onEventHandler",
            FunctionProps.builder()
                .runtime(Runtime.JAVA_11)
                .code(
                    Code.fromAsset(
                        "./AdConnectorCustomResource",
                        AssetOptions.builder()
                            .assetHashType(AssetHashType.CUSTOM)
                            .assetHash(hashDirectory("./AdConnectorCustomResource/src", false))
                            .bundling(
                                builderOptions
                                    .command(adConnectorCustomResourcePackagingInstructions)
                                    .build())
                            .build()))
                .handler("com.ilmlf.adconnector.customresource.OnEventHandler")
                .memorySize(1024)
                .timeout(Duration.seconds(10))
                .logRetention(RetentionDays.ONE_WEEK)
                .build());

    /*
      Our OnEventHandler needs to access our DomainAdminPassword secret.
      Hence, we grant the GetSecretValue permission to the lambda function.
    */
    onEventHandler.addToRolePolicy(
        new PolicyStatement(
            PolicyStatementProps.builder()
                .actions(singletonList("secretsmanager:GetSecretValue"))
                .resources(Collections.singletonList(props.secretId))
                .build()));

    /*
      Our OnEventHandler also needs to make various VPC API calls.
      The VPC service is located under EC2, and hence most of the
      permissions we grant are of the form ec2:*
    */
    onEventHandler.addToRolePolicy(
        new PolicyStatement(
            PolicyStatementProps.builder()
                .actions(
                    Arrays.asList(
                        "secretsmanager:GetSecretValue",
                        "ds:ConnectDirectory",
                        "ds:DeleteDirectory",
                        "ec2:DescribeSubnets",
                        "ec2:DescribeVpcs",
                        "ec2:CreateSecurityGroup",
                        "ec2:CreateNetworkInterface",
                        "ec2:DescribeNetworkInterfaces",
                        "ec2:AuthorizeSecurityGroupIngress",
                        "ec2:AuthorizeSecurityGroupEgress",
                        "ec2:CreateTags"))
                .resources(Collections.singletonList("*"))
                .build()));

    /*
      The isCompleteHandler is a function that is periodically called to check
      if the resource creation processes initiated in onEventHandler have completed.
      Here we are defining it in a similar way to how we defined the OnEventHandler component.
    */
    Function isCompleteHandler =
        new Function(
            this,
            "isCompleteHandler",
            FunctionProps.builder()
                .runtime(Runtime.JAVA_11)
                .code(
                    Code.fromAsset(
                        "./AdConnectorCustomResource",
                        AssetOptions.builder()
                            .assetHashType(AssetHashType.CUSTOM)
                            .assetHash(hashDirectory("./AdConnectorCustomResource/src", false))
                            .bundling(
                                builderOptions
                                    .command(adConnectorCustomResourcePackagingInstructions)
                                    .build())
                            .build()))
                .handler("com.ilmlf.adconnector.customresource.IsCompleteHandler")
                .memorySize(1024)
                .timeout(Duration.seconds(10))
                .logRetention(RetentionDays.ONE_WEEK)
                .build());

    /*
      The IsCompleteHandler checks if the Active Directory connection has
      completed by checking if any Active Directories are listed in the Directory Service.
      Hence we must grant the Directory Service's 'DescribeDirectories' permission.
    */
    isCompleteHandler.addToRolePolicy(
        new PolicyStatement(
            PolicyStatementProps.builder()
                .actions(singletonList("ds:DescribeDirectories"))
                .resources(Collections.singletonList("*"))
                .build()));

    /*
      The Provider associates the onEvent and isComplete handlers to the custom resource.
    */
    Provider provider =
        new Provider(
            scope,
            "adConnectorProvider",
            ProviderProps.builder()
                .onEventHandler(onEventHandler)
                .isCompleteHandler(isCompleteHandler)
                .build());

    /*
      Define the properties that will be passed to our lambda handler functions.
      - vpcId is the identifier of the VPC in which to create the AD Connector
      - domainName is the Active Directory Domain Name
      - dnsIps is a list of IP addresses for the DNS hosts of the on-premise infrastructure
      - subnetIds are the identifiers of the subnets in which to place the AD connector
      - secretId is the ID of the Secrets Manager 'DomainAdminPassword' secret
    */
    TreeMap resourceProperties = new TreeMap();
    resourceProperties.put("vpcId", props.vpcId);
    resourceProperties.put("domainName", props.domainName);
    resourceProperties.put("dnsIps", props.dnsIps);
    resourceProperties.put("subnetIds", props.subnetIds);
    resourceProperties.put("secretId", props.secretId);

    /*
      Finally, create the CDK Custom Resource using all the previous parts we defined.
    */
    CustomResource resource =
        new CustomResource(
            scope,
            "ADConnector",
            CustomResourceProps.builder()
                .serviceToken(provider.getServiceToken())
                .resourceType("Custom::ADConnector")
                .properties(resourceProperties)
                .build());
    this.directoryId = resource.getAttString("DirectoryId");
  }