Skip to content

Commit 7fe29d2

Browse files
committed
Add validation of DirectoryService/AdditionalSssdConfigs: a failure is emitted when the customer is overriding protected properties. Extend AD integration tests to cover the use of DirectoryService/AdditionalSssdConfigs to set a simple access provider.
Signed-off-by: Giacomo Marciani <mgiacomo@amazon.com>
1 parent 4c251fb commit 7fe29d2

File tree

7 files changed

+154
-1
lines changed

7 files changed

+154
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ CHANGELOG
88
- Execute SSH key creation alongside with the creation of HOME directory, i.e.
99
during SSH login, when switching to another user and when executing a command as another user.
1010
- Add support for both FQDN and LDAP Distinguished Names in the configuration parameter `DirectoryService/DomainName`. The new validator now checks both the syntaxes.
11-
- New `update_directory_service_password.sh` script deployed on the head node supports the manual update of the Active Directory password in the SSSD configuration.
11+
- New `update_directory_service_password.sh` script deployed on the head node supports the manual update of the Active Directory password in the SSSD configuration.
1212
The password is retrieved by the AWS Secrets Manager as from the cluster configuration.
1313
- Add support to deploy API infrastructure in environments without a default VPC.
14+
- Add validation for `DirectoryService/AdditionalSssdConfigs` to fail in case of invalid overrides.
1415

1516
**CHANGES**
1617
- Disable deeper C-States in x86_64 official AMIs and AMIs created through `build-image` command, to guarantee high performance and low latency.

cli/src/pcluster/config/cluster_config.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
SharedStorageNameValidator,
8484
)
8585
from pcluster.validators.directory_service_validators import (
86+
AdditionalSssdConfigsValidator,
8687
DomainAddrValidator,
8788
DomainNameValidator,
8889
LdapTlsReqCertValidator,
@@ -709,6 +710,12 @@ def _register_validators(self):
709710
)
710711
if self.ldap_tls_req_cert:
711712
self._register_validator(LdapTlsReqCertValidator, ldap_tls_reqcert=self.ldap_tls_req_cert)
713+
if self.additional_sssd_configs:
714+
self._register_validator(
715+
AdditionalSssdConfigsValidator,
716+
additional_sssd_configs=self.additional_sssd_configs,
717+
ldap_access_filter=self.ldap_access_filter,
718+
)
712719

713720

714721
class ClusterIam(Resource):

cli/src/pcluster/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,6 @@
156156
# see https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html
157157
NODEJS_MIN_VERSION = "10.13.0"
158158
NODEJS_INCOMPATIBLE_VERSION_RANGE = ["13.0.0", "13.6.0"]
159+
160+
# DirectoryService
161+
DIRECTORY_SERVICE_RESERVED_SETTINGS = {"id_provider": "ldap"}

cli/src/pcluster/validators/directory_service_validators.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import re
1313
from urllib.parse import urlparse
1414

15+
from pcluster.constants import DIRECTORY_SERVICE_RESERVED_SETTINGS
1516
from pcluster.validators.common import FailureLevel, Validator
1617

1718

@@ -78,3 +79,32 @@ def _validate(self, ldap_tls_reqcert):
7879
f"For security reasons it's recommended to use {' or '.join(values_requiring_cert_validation)}",
7980
FailureLevel.WARNING,
8081
)
82+
83+
84+
class AdditionalSssdConfigsValidator(Validator):
85+
"""AdditionalSssdConfigs validator."""
86+
87+
def _validate(self, additional_sssd_configs, ldap_access_filter):
88+
"""Validate that AdditionalSssdConfigs does not introduce unacceptable values."""
89+
for config_key, accepted_value in DIRECTORY_SERVICE_RESERVED_SETTINGS.items():
90+
if config_key in additional_sssd_configs:
91+
actual_value = additional_sssd_configs[config_key]
92+
if actual_value != accepted_value:
93+
self._add_failure(
94+
f"Cannot override the SSSD property '{config_key}' "
95+
f"with value '{actual_value}'. "
96+
f"Allowed value is: '{accepted_value}'. "
97+
"Please refer to ParallelCluster official documentation for more information.",
98+
FailureLevel.ERROR,
99+
)
100+
101+
if "access_provider" in additional_sssd_configs:
102+
actual_access_provider = additional_sssd_configs["access_provider"]
103+
if ldap_access_filter is not None and actual_access_provider != "ldap":
104+
self._add_failure(
105+
"Cannot override the SSSD property 'access_provider' "
106+
f"with value '{actual_access_provider}' when LdapAccessFilter is specified. "
107+
"Allowed value is: 'ldap'. "
108+
"Please refer to ParallelCluster official documentation for more information.",
109+
FailureLevel.ERROR,
110+
)

cli/tests/pcluster/validators/test_directory_service_validators.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import pytest
1212

1313
from pcluster.validators.directory_service_validators import (
14+
AdditionalSssdConfigsValidator,
1415
DomainAddrValidator,
1516
DomainNameValidator,
1617
LdapTlsReqCertValidator,
@@ -108,3 +109,44 @@ def test_domain_addr_protocol(domain_addr, additional_sssd_configs, expected_mes
108109
def test_ldap_tls_reqcert_validator(ldap_tls_reqcert, expected_message):
109110
actual_failures = LdapTlsReqCertValidator().execute(ldap_tls_reqcert=ldap_tls_reqcert)
110111
assert_failure_messages(actual_failures, expected_message)
112+
113+
114+
@pytest.mark.parametrize(
115+
"additional_sssd_configs, ldap_access_filter, expected_message",
116+
[
117+
("WHATEVER", "WHATEVER", None),
118+
(
119+
{"id_provider": "ldap", "whatever_property": "WHATEVER"},
120+
"WHATEVER",
121+
None,
122+
),
123+
(
124+
{"access_provider": "ldap", "whatever_property": "WHATEVER"},
125+
"WHATEVER",
126+
None,
127+
),
128+
(
129+
{"access_provider": "NOT_ldap", "whatever_property": "WHATEVER"},
130+
None,
131+
None,
132+
),
133+
(
134+
{"id_provider": "NOT_ldap", "whatever_property": "WHATEVER"},
135+
"WHATEVER",
136+
"Cannot override the SSSD property 'id_provider' with value 'NOT_ldap'. Allowed value is: 'ldap'. "
137+
"Please refer to ParallelCluster official documentation for more information.",
138+
),
139+
(
140+
{"access_provider": "NOT_ldap", "whatever_property": "WHATEVER"},
141+
"WHATEVER",
142+
"Cannot override the SSSD property 'access_provider' with value 'NOT_ldap' "
143+
"when LdapAccessFilter is specified. Allowed value is: 'ldap'. "
144+
"Please refer to ParallelCluster official documentation for more information.",
145+
),
146+
],
147+
)
148+
def test_additional_sssd_configs(additional_sssd_configs, ldap_access_filter, expected_message):
149+
actual_failures = AdditionalSssdConfigsValidator().execute(
150+
additional_sssd_configs=additional_sssd_configs, ldap_access_filter=ldap_access_filter
151+
)
152+
assert_failure_messages(actual_failures, expected_message)

tests/integration-tests/tests/ad_integration/test_ad_integration.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,8 @@ def test_ad_integration(
811811
_run_user_workloads(users, test_datadir, remote_command_executor)
812812
logging.info("Testing pcluster update and generate ssh keys for user")
813813
_check_ssh_key_generation(users[0], remote_command_executor, scheduler_commands, False)
814+
815+
# Verify access control with ldap access provider.
814816
updated_config_file = pcluster_config_reader(config_file="pcluster.config.update.yaml", **config_params)
815817
cluster.update(str(updated_config_file), force_update="true")
816818
# Reset stateful connection variables after the cluster update
@@ -823,6 +825,20 @@ def test_ad_integration(
823825
logging.info(f"Checking SSH access for user {user.alias}")
824826
_check_ssh_auth(user=user, expect_success=user.alias != "PclusterUser2")
825827

828+
# Verify access control with simple access provider.
829+
# With this test we also verify that AdditionalSssdConfigs is working properly.
830+
updated_config_file = pcluster_config_reader(config_file="pcluster.config.update2.yaml", **config_params)
831+
cluster.update(str(updated_config_file), force_update="true")
832+
# Reset stateful connection variables after the cluster update
833+
remote_command_executor = RemoteCommandExecutor(cluster)
834+
scheduler_commands = get_scheduler_commands(scheduler, remote_command_executor)
835+
for user in users:
836+
user.reset_stateful_connection_objects(remote_command_executor)
837+
_check_ssh_key_generation(users[1], remote_command_executor, scheduler_commands, True)
838+
for user in users:
839+
logging.info(f"Checking SSH access for user {user.alias}")
840+
_check_ssh_auth(user=user, expect_success=user.alias != "PclusterUser0")
841+
826842

827843
def _check_ssh_auth(user, expect_success=True):
828844
try:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Image:
2+
Os: {{ os }}
3+
HeadNode:
4+
InstanceType: {{ head_node_instance_type }}
5+
Networking:
6+
SubnetId: {{ public_subnet_id }}
7+
Ssh:
8+
KeyName: {{ key_name }}
9+
Imds:
10+
Secured: {{ imds_secured }}
11+
Scheduling:
12+
Scheduler: {{ scheduler }}
13+
SlurmQueues:
14+
- Name: compute
15+
ComputeResources:
16+
- Name: cit
17+
InstanceType: {{ compute_instance_type }}
18+
MinCount: 2
19+
MaxCount: 150
20+
Networking:
21+
SubnetIds:
22+
- {{ private_subnet_id }}
23+
Monitoring:
24+
Logs:
25+
CloudWatch:
26+
Enabled: true
27+
RetentionInDays: 14
28+
SharedStorage:
29+
- MountDir: /shared
30+
Name: fsx
31+
StorageType: FsxLustre
32+
FsxLustreSettings:
33+
StorageCapacity: 2400
34+
- MountDir: /ebs
35+
Name: ebs
36+
StorageType: Ebs
37+
- MountDir: /efs
38+
Name: efs
39+
StorageType: Efs
40+
DirectoryService:
41+
DomainName: {{ ldap_search_base }}
42+
DomainAddr: {{ ldap_uri }}
43+
PasswordSecretArn: {{ password_secret_arn }}
44+
DomainReadOnlyUser: {{ ldap_default_bind_dn }}
45+
LdapTlsCaCert: {{ ldap_tls_ca_cert }}
46+
LdapTlsReqCert: {{ ldap_tls_req_cert }}
47+
GenerateSshKeysForUsers: true
48+
AdditionalSssdConfigs:
49+
debug_level: "0x1ff"
50+
{% if directory_protocol == "ldap" %}
51+
ldap_auth_disable_tls_never_use_in_production: True
52+
{% endif %}
53+
access_provider: simple
54+
simple_deny_users: PclusterUser0

0 commit comments

Comments
 (0)