LDAPS Management

This documentation details the process to enable LDAPS between ActiveDirectory and your CCME environment.

Architecture

The following description explains the ActiveDirectoryD LDAPS environment.

  • The LDAP client sends an LDAPS request to the NetworkLoadBalancer on TCP port 636 (LDAPS).

  • The NetworkLoadBalancer terminates the TLS session and decrypts the traffic using a certificate. The NetworkLoadBalancer sends the decrypted LDAP traffic to ActiveDirectory on TCP port 389 (LDAP).

  • The ActiveDirectoryD domain controllers send an LDAP response to the NetworkLoadBalancer. The NetworkLoadBalancer encrypts the response and sends it to the client.

The following architrecture diagram illustrates how the solution works and shows the prerequisites (listed in the following section).

image_ldaps_architecture

Prerequisites

  • 2 Private Subnets (different from CMH/Clusters subnets)

    • The subnets must be in two different AvailabilityZones (AZs)

    • First subnet NetworkAdSubnetFirstAzId

    • Second subnet NetworkAdSubnetSecondAZ

  • VPC configuration

    • VPC ACL rules in order of decreasing priority:

      • Inbound:

        • Allow protocol TCP, port 389 from NetworkAdSubnetFirstAzIdCidr

        • Deny protocol TCP, port 389 from 0.0.0.0/0

      • Outbound:

        • Allow protocol TCP, port 389 to NetworkAdSubnetSecondAZCidr

        • Deny protocol TCP, port 389 to 0.0.0.0/0

Network Load Balancing

The load balancing is composed of:

Create the NetworkLoadBalancer

The NetworkLoadBalancer creation requires the following parameters:

  • NetworkAdSubnetFirstAzId: The first Active Directory private subnet from the prerequisites

  • NetworkAdSubnetSecondAZ: The second Active Directory private subnet from the prerequisites

The following CloudFormation code (yaml format) details the NetworkLoadBalancer configuration:

ccmeNetworkLoadBalancer:
  Type: AWS::ElasticLoadBalancingV2::LoadBalancer
  Properties:
    Name: 'ccmeNLB'
    Type: network
    Scheme: internal
    Subnets:
      - Ref: NetworkAdSubnetFirstAzId
      - Ref: NetworkAdSubnetSecondAZ
    Tags:
      - Key: Name
        Value: 'ccmeNLB'

Create the NetworkLoadBalancerTargetGroup

The NetworkLoadBalancerTargetGroup creation requires the following parameters:

  • GlobalVpcId: The VPC from prerequisites

  • ActiveDirectoryUri: One or two URIs (comma delimited in the following example)

The following CloudFormation code (yaml format) details the NetworkLoadBalancerTargetGroup configuration:

ccmeNetworkLoadBalancerTargetGroup:
  Type: AWS::ElasticLoadBalancingV2::TargetGroup
  Properties:
    Port: 389
    Protocol: TCP
    VpcId:
      Ref: GlobalVpcId
    HealthCheckEnabled: True
    HealthCheckIntervalSeconds: 10
    HealthCheckPort: 389
    HealthCheckProtocol: TCP
    HealthCheckTimeoutSeconds: 10
    HealthyThresholdCount: 3
    TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: 60
    Targets:
      - Id: # IP of the ActiveDirectory in the first private subnet from prerequisites
          'Fn::Select':
            - '0'
            - 'Fn::Split':
              - ','
              - Ref: ActiveDirectoryUri
        Port: 389
      - Id: # IP of the ActiveDirectory in the second private subnet from prerequisites
          'Fn::Select':
            - '1'
            - 'Fn::Split':
              - ','
              - Ref: ActiveDirectoryUri
        Port: 389
    TargetType: ip

Create the certificate

  • Create a certificate and a private key based on the NetworkLoadBalancer DomainName (DN)

  • Import the certificate and the private key in the AWS Certificate Manager (ACM)

  • Import the certificate to your CCME sources bucket and its correct subfolder

  • Clean the certificate and private key from your local files system

The certificate creation requires the following parameters:

  • CCME_NLB_DNS: The DNS of the previously created NetworkLoadBalancer (e.g., ccmeNLB-ea2a53d6ac284e9f.elb.eu-west-1.amazonaws.com)

  • AWS_REGION: The AWS Region of the previously create NetworkLoadBalancer (e.g., eu-west-1)

  • CCME_SOURCES: The CCME S3 source bucket and its optional subfolder(s) (e.g., ucit-ccme/ccme-subfolder)

The following script automatically creates and import a certificate in AWS Certificate Manager:

#!/bin/bash
################################################################################
# Copyright (c) 2017-2024 UCit SAS
# All Rights Reserved
#
# This software is the confidential and proprietary information
# of UCit SAS ("Confidential Information").
# You shall not disclose such Confidential Information
# and shall use it only in accordance with the terms of
# the license agreement you entered into with UCit.
################################################################################

CCME_NLB_DNS=""     # Example: "ccmeNLB-ea2a53d6ac284e9f.elb.eu-west-1.amazonaws.com"
AWS_REGION=""       # Example: "eu-west-1"
CCME_SOURCES=""     # Example: "ucit-ccme/ccme-subfolder"

CCME_NLB_PRIVATE_KEY="${CCME_NLB_DNS}.key"
CCME_NLB_CERTIFICATE="${CCME_NLB_DNS}.crt"

echo "[Create] Certificate and private key for the CCME NetworkLoadBalancerListener"
printf '.\n.\n.\n.\n.\n%s\n.\n' "${CCME_NLB_DNS}" | openssl req -x509 -sha256 -nodes -newkey rsa:2048 -keyout "${CCME_NLB_PRIVATE_KEY}" -days 365 -out "${CCME_NLB_CERTIFICATE}"

echo "[Import] Certificate and private key to AWS Certificate Manager (ACM)"
CCME_NLB_ACM_ARN=$(aws acm import-certificate --certificate "file://${CCME_NLB_CERTIFICATE}" --private-key "file://${CCME_NLB_PRIVATE_KEY}" --region "${AWS_REGION}" --output text)
echo "[Info] The certificate ARN is \"${CCME_NLB_ACM_ARN}\""

echo "[Import] Certificate to the CCME bucket"
aws s3 cp "${CCME_NLB_CERTIFICATE}" "s3://${CCME_SOURCES}/CCME/conf/"

echo "[Clean] Certificate and private key from the local file system"
rm -rf "${CCME_NLB_PRIVATE_KEY}" "${CCME_NLB_CERTIFICATE}"

Create the NetworkLoadBalancerListener

The NetworkLoadBalancerListener creation requires the following parameters:

  • ccmeNetworkLoadBalancerTargetGroup: The ARN of the previously created NetworkLoadBalancerTargetGroup

  • ActiveDirectoryCertificateArn: The ARN of the previously created certificate in AWS Certificate Manager

The following CloudFormation code (yaml format) details the NetworkLoadBalancerListener configuration:

ccmeNetworkLoadBalancerListener:
  Type: AWS::ElasticLoadBalancingV2::Listener
  Properties:
    DefaultActions:
      - Type: forward
        TargetGroupArn:
          Ref: ccmeNetworkLoadBalancerTargetGroup
    LoadBalancerArn:
      Ref: ccmeNetworkLoadBalancer
    Port: 636
    Protocol: TLS
    SslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01
    Certificates:
      - CertificateArn:
          Ref: ActiveDirectoryCertificateArn

Example: Complete load balancing yaml template

The following yaml template is a NetworkLoadBalancer, Listener and TargetGroup example.

Warning

The template requires the ARN of a certificate from AWS Certificate Manager. In consequence:

  • The certificate DomainName will not match the NetworkLoadBalancer DomainNameServer.

  • The DirectoryService pcluster parameter LdapTlsReqCert must be set to allow.

To fix it, you must create (manually or with the previous script) a new certificate:

  • This new certificate must be based on the NetworkLoadBalancer DomainNameServer.

  • The NetworkLoadBalancer DomainNameServer is named ccmeNetworkLoadBalancerDns in the following template outputs.

The following yaml template is a NetworkLoadBalancer, Listener and TargetGroup example:

################################################################################
# Copyright (c) 2017-2024 UCit SAS
# All Rights Reserved
#
# This software is the confidential and proprietary information
# of UCit SAS ("Confidential Information").
# You shall not disclose such Confidential Information
# and shall use it only in accordance with the terms of
# the license agreement you entered into with UCit.
################################################################################
AWSTemplateFormatVersion: 2010-09-09
Description: 'UCit CCME: NetworkLoadBalancer for ActiveDirectory LDAPs'
Parameters:
  NetworkVpcId:
    Description: Id of an existing VPC for the Management Host location
    Type: 'AWS::EC2::VPC::Id'
    AllowedPattern: .+
  NetworkAdSubnetFirstAzId:
    Description: Id of an existing private subnet in a first AvailabilityZone (AZ) for the NetworkLoadBalancer (NLB)
    Type: 'AWS::EC2::Subnet::Id'
    AllowedPattern: .+
  NetworkAdSubnetSecondAZ:
    Description: Id of an existing private subnet in a second AvailabilityZone (AZ) for the NetworkLoadBalancer (NLB)
    Type: 'AWS::EC2::Subnet::Id'
    AllowedPattern: .+
  ActiveDirectoryUri:
    Description: Specify the URIs (maximum 2) of an existing ActiveDirectory
    Type: String
    AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}),(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})'
  ActiveDirectoryCertificateArn:
    Description: CCME Domain Certificate for the Active Directory Application Load Balancer (ARN of an existing certificate in ACM)
    Type: String
    AllowedPattern: '^(arn:aws:acm:\w+(?:-\w+)+:\d{12}:certificate/)([a-zA-Z0-9.\-/_+=@]+)$'
  ActiveDirectoryNetworkLoadBlancerSecurityGroup:
    Description: Id of an existing security group for the NetworkLoadBalancer (NLB)
    Type: 'AWS::EC2::SecurityGroup::Id'
    AllowedPattern: .+
Resources:
  ccmeNetworkLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: 'ccmeNLB'
      Type: network
      Scheme: internal
      SecurityGroups:
        - Ref: ActiveDirectoryNetworkLoadBlancerSecurityGroup
      Subnets:
        - Ref: NetworkAdSubnetFirstAzId
        - Ref: NetworkAdSubnetSecondAZ
      Tags:
        - Key: Name
          Value: 'ccmeNLB'
        # This mandatory tag is used to identify CCME resources and
        # allow actions over these resources.
        - Key: 'ccme:ad:nlb:stack-name'
          Value:
            Ref: 'AWS::StackName'
  ccmeNetworkLoadBalancerTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Port: 389
      Protocol: TCP
      VpcId:
        Ref: NetworkVpcId
      HealthCheckEnabled: True
      HealthCheckIntervalSeconds: 10
      HealthCheckPort: 389
      HealthCheckProtocol: TCP
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 3
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: 60
      Targets:
        - Id:
            'Fn::Select':
              - '0'
              - 'Fn::Split':
                - ','
                - Ref: ActiveDirectoryUri
          Port: 389
        - Id:
            'Fn::Select':
              - '1'
              - 'Fn::Split':
                - ','
                - Ref: ActiveDirectoryUri
          Port: 389
      TargetType: ip
  ccmeNetworkLoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn:
            Ref: ccmeNetworkLoadBalancerTargetGroup
      LoadBalancerArn:
        Ref: ccmeNetworkLoadBalancer
      Port: 636
      Protocol: TLS
      SslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01
      Certificates:
        - CertificateArn:
            Ref: ActiveDirectoryCertificateArn
Outputs:
  ccmeNetworkLoadBalancerArn:
    Description: Dns of the NetworkLoadBalancer
    Value:
      'Fn::GetAtt':
        - ccmeNetworkLoadBalancer
        - LoadBalancerArn
  ccmeNetworkLoadBalancerDns:
    Description: Dns of the NetworkLoadBalancer
    Value:
      'Fn::GetAtt':
        - ccmeNetworkLoadBalancer
        - DNSName

Cluster configuration

This section describes the cluster configuration to contact your ActiveDirectory using the NetworkLoadBalancer ldaps.

  • The NetworkLoadBalancer DomainNameServer (CCME_NLB_DNS in the following example) is required

  • The DirectoryService parameter LdapTlsReqCert must be set to:

    • hard if the NetworkLoadBalancer DomainNameServer matches the certificate DomainName

    • allow if other cases

  • The DirectoryService parameter LdapTlsCaCert must be set to the certificate path of the CCME solution

    • Usually in /opt/CCME/conf/

    • Example: /opt/CCME/conf/ccmeNLB-ea2a53d6ac284e9f.elb.eu-west-1.amazonaws.com.crt

Configuration of AWS ParallelCluster DirectoryService:

DirectoryService:
  DomainName: ${CCME_AD_DIR_NAME}
    # Example: "ccme.ad"
  DomainAddr: ldaps://${CCME_NLB_DNS}
    # Example: "ldaps://ccmeNLB-ea2a53d6ac284e9f.elb.eu-west-1.amazonaws.com"
  PasswordSecretArn: ${CCME_AD_READ_ONLY_USER_PASSWORD}
    # Example: "arn:aws:secretsmanager:eu-west-1:012345678910:secret:ccme-readonlyuser-password-1ab2cd"
  DomainReadOnlyUser: ${CCME_AD_READ_ONLY_USER_DN}
    # Example (SimpleAD): "cn=Administrator,cn=Users,dc=ccme,dc=ad"
    # Example (ManagedAD): "cn=Admin,cn=Users,dc=ccme,dc=ad"
  # LdapTlsReqCert must be "allow" instead of "hard" if the certificate
  # Domain Name (DN) differs from the NetworkLoadBalancer Domain Name (DN).
  LdapTlsReqCert: hard
  LdapTlsCaCert: /opt/CCME/conf/${CCME_NLB_DNS}.crt
    # Example: "/opt/CCME/conf/ccmeNLB-ea2a53d6ac284e9f.elb.eu-west-1.amazonaws.com.crt"