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).
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
fromNetworkAdSubnetFirstAzIdCidr
Deny protocol TCP, port
389
from0.0.0.0/0
Outbound:
Allow protocol TCP, port
389
toNetworkAdSubnetSecondAZCidr
Deny protocol TCP, port
389
to0.0.0.0/0
Network Load Balancing
The load balancing is composed of:
-
It listens to the port
636
(LDAPS)It uses a certificate presents in AWS Certificate Manager (ACM) for TLS
NetworkLoadBalancerTargetGroup
It forwards the traffic from the NetworkLoadBalancerListener to Active Directory URIs on port
389
Create the NetworkLoadBalancer
The NetworkLoadBalancer creation requires the following parameters:
NetworkAdSubnetFirstAzId
: The first Active Directory private subnet from the prerequisitesNetworkAdSubnetSecondAZ
: 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 prerequisitesActiveDirectoryUri
: 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 NetworkLoadBalancerTargetGroupActiveDirectoryCertificateArn
: 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 NetworkLoadBalancerDomainNameServer
.The DirectoryService pcluster parameter
LdapTlsReqCert
must be set toallow
.
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 namedccmeNetworkLoadBalancerDns
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 requiredThe DirectoryService parameter
LdapTlsReqCert
must be set to:
hard
if the NetworkLoadBalancerDomainNameServer
matches the certificateDomainName
allow
if other casesThe 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"