mirror of
https://github.com/ansible/awx.git
synced 2026-04-06 02:29:21 -02:30
Remove LDAP authentication (#15546)
Remove LDAP authentication from AWX
This commit is contained in:
committed by
jessicamack
parent
6dea7bfe17
commit
f22b192fb4
@@ -642,10 +642,7 @@ class UserAccess(BaseAccess):
|
||||
"""
|
||||
|
||||
model = User
|
||||
prefetch_related = (
|
||||
'profile',
|
||||
'resource',
|
||||
)
|
||||
prefetch_related = ('resource',)
|
||||
|
||||
def filtered_queryset(self):
|
||||
if settings.ORG_ADMINS_CAN_SEE_ALL_USERS and (self.user.admin_of_organizations.exists() or self.user.auditor_of_organizations.exists()):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -11,7 +10,7 @@ from awx.conf import settings_registry
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Dump the current auth configuration in django_ansible_base.authenticator format, currently supports LDAP and SAML'
|
||||
help = 'Dump the current auth configuration in django_ansible_base.authenticator format, currently supports SAML'
|
||||
|
||||
DAB_SAML_AUTHENTICATOR_KEYS = {
|
||||
"SP_ENTITY_ID": True,
|
||||
@@ -27,20 +26,6 @@ class Command(BaseCommand):
|
||||
"CALLBACK_URL": False,
|
||||
}
|
||||
|
||||
DAB_LDAP_AUTHENTICATOR_KEYS = {
|
||||
"SERVER_URI": True,
|
||||
"BIND_DN": False,
|
||||
"BIND_PASSWORD": False,
|
||||
"CONNECTION_OPTIONS": False,
|
||||
"GROUP_TYPE": True,
|
||||
"GROUP_TYPE_PARAMS": True,
|
||||
"GROUP_SEARCH": False,
|
||||
"START_TLS": False,
|
||||
"USER_DN_TEMPLATE": True,
|
||||
"USER_ATTR_MAP": True,
|
||||
"USER_SEARCH": False,
|
||||
}
|
||||
|
||||
def is_enabled(self, settings, keys):
|
||||
missing_fields = []
|
||||
for key, required in keys.items():
|
||||
@@ -50,41 +35,6 @@ class Command(BaseCommand):
|
||||
return False, missing_fields
|
||||
return True, None
|
||||
|
||||
def get_awx_ldap_settings(self) -> dict[str, dict[str, Any]]:
|
||||
awx_ldap_settings = {}
|
||||
|
||||
for awx_ldap_setting in settings_registry.get_registered_settings(category_slug='ldap'):
|
||||
key = awx_ldap_setting.removeprefix("AUTH_LDAP_")
|
||||
value = getattr(settings, awx_ldap_setting, None)
|
||||
awx_ldap_settings[key] = value
|
||||
|
||||
grouped_settings = {}
|
||||
|
||||
for key, value in awx_ldap_settings.items():
|
||||
match = re.search(r'(\d+)', key)
|
||||
index = int(match.group()) if match else 0
|
||||
new_key = re.sub(r'\d+_', '', key)
|
||||
|
||||
if index not in grouped_settings:
|
||||
grouped_settings[index] = {}
|
||||
|
||||
grouped_settings[index][new_key] = value
|
||||
if new_key == "GROUP_TYPE" and value:
|
||||
grouped_settings[index][new_key] = type(value).__name__
|
||||
|
||||
if new_key == "SERVER_URI" and value:
|
||||
value = value.split(", ")
|
||||
grouped_settings[index][new_key] = value
|
||||
|
||||
if type(value).__name__ == "LDAPSearch":
|
||||
data = []
|
||||
data.append(value.base_dn)
|
||||
data.append("SCOPE_SUBTREE")
|
||||
data.append(value.filterstr)
|
||||
grouped_settings[index][new_key] = data
|
||||
|
||||
return grouped_settings
|
||||
|
||||
def get_awx_saml_settings(self) -> dict[str, Any]:
|
||||
awx_saml_settings = {}
|
||||
for awx_saml_setting in settings_registry.get_registered_settings(category_slug='saml'):
|
||||
@@ -157,23 +107,6 @@ class Command(BaseCommand):
|
||||
else:
|
||||
data.append({"SAML_missing_fields": saml_missing_fields})
|
||||
|
||||
# dump LDAP settings
|
||||
awx_ldap_group_settings = self.get_awx_ldap_settings()
|
||||
for awx_ldap_name, awx_ldap_settings in awx_ldap_group_settings.items():
|
||||
awx_ldap_enabled, ldap_missing_fields = self.is_enabled(awx_ldap_settings, self.DAB_LDAP_AUTHENTICATOR_KEYS)
|
||||
if awx_ldap_enabled:
|
||||
data.append(
|
||||
self.format_config_data(
|
||||
awx_ldap_enabled,
|
||||
awx_ldap_settings,
|
||||
"ldap",
|
||||
self.DAB_LDAP_AUTHENTICATOR_KEYS,
|
||||
f"LDAP_{awx_ldap_name}",
|
||||
)
|
||||
)
|
||||
else:
|
||||
data.append({f"LDAP_{awx_ldap_name}_missing_fields": ldap_missing_fields})
|
||||
|
||||
# write to file if requested
|
||||
if options["output_file"]:
|
||||
# Define the path for the output JSON file
|
||||
|
||||
@@ -93,7 +93,7 @@ class DisableLocalAuthMiddleware(MiddlewareMixin):
|
||||
user = request.user
|
||||
if not user.pk:
|
||||
return
|
||||
if not (user.profile.ldap_dn or user.social_auth.exists() or user.enterprise_auth.exists()):
|
||||
if not (user.social_auth.exists() or user.enterprise_auth.exists()):
|
||||
logout(request)
|
||||
|
||||
|
||||
|
||||
16
awx/main/migrations/0196_delete_profile.py
Normal file
16
awx/main/migrations/0196_delete_profile.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 4.2.10 on 2024-08-09 16:47
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0195_EE_permissions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Profile',
|
||||
),
|
||||
]
|
||||
@@ -18,7 +18,7 @@ from ansible_base.lib.utils.models import user_summary_fields
|
||||
# AWX
|
||||
from awx.main.models.base import BaseModel, PrimordialModel, accepts_json, CLOUD_INVENTORY_SOURCES, VERBOSITY_CHOICES # noqa
|
||||
from awx.main.models.unified_jobs import UnifiedJob, UnifiedJobTemplate, StdoutMaxBytesExceeded # noqa
|
||||
from awx.main.models.organization import Organization, Profile, Team, UserSessionMembership # noqa
|
||||
from awx.main.models.organization import Organization, Team, UserSessionMembership # noqa
|
||||
from awx.main.models.credential import Credential, CredentialType, CredentialInputSource, ManagedCredentialType, build_safe_env # noqa
|
||||
from awx.main.models.projects import Project, ProjectUpdate # noqa
|
||||
from awx.main.models.receptor_address import ReceptorAddress # noqa
|
||||
@@ -292,7 +292,6 @@ activity_stream_registrar.connect(Job)
|
||||
activity_stream_registrar.connect(AdHocCommand)
|
||||
# activity_stream_registrar.connect(JobHostSummary)
|
||||
# activity_stream_registrar.connect(JobEvent)
|
||||
# activity_stream_registrar.connect(Profile)
|
||||
activity_stream_registrar.connect(Schedule)
|
||||
activity_stream_registrar.connect(NotificationTemplate)
|
||||
activity_stream_registrar.connect(Notification)
|
||||
|
||||
@@ -15,8 +15,8 @@ from ansible_base.resource_registry.fields import AnsibleResourceField
|
||||
|
||||
# AWX
|
||||
from awx.api.versioning import reverse
|
||||
from awx.main.fields import AutoOneToOneField, ImplicitRoleField, OrderedManyToManyField
|
||||
from awx.main.models.base import BaseModel, CommonModel, CommonModelNameNotUnique, CreatedModifiedModel, NotificationFieldsModel
|
||||
from awx.main.fields import ImplicitRoleField, OrderedManyToManyField
|
||||
from awx.main.models.base import BaseModel, CommonModel, CommonModelNameNotUnique, NotificationFieldsModel
|
||||
from awx.main.models.rbac import (
|
||||
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR,
|
||||
ROLE_SINGLETON_SYSTEM_AUDITOR,
|
||||
@@ -24,7 +24,7 @@ from awx.main.models.rbac import (
|
||||
from awx.main.models.unified_jobs import UnifiedJob
|
||||
from awx.main.models.mixins import ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin
|
||||
|
||||
__all__ = ['Organization', 'Team', 'Profile', 'UserSessionMembership']
|
||||
__all__ = ['Organization', 'Team', 'UserSessionMembership']
|
||||
|
||||
|
||||
class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin):
|
||||
@@ -167,22 +167,6 @@ class Team(CommonModelNameNotUnique, ResourceMixin):
|
||||
return reverse('api:team_detail', kwargs={'pk': self.pk}, request=request)
|
||||
|
||||
|
||||
class Profile(CreatedModifiedModel):
|
||||
"""
|
||||
Profile model related to User object. Currently stores LDAP DN for users
|
||||
loaded from LDAP.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
app_label = 'main'
|
||||
|
||||
user = AutoOneToOneField('auth.User', related_name='profile', editable=False, on_delete=models.CASCADE)
|
||||
ldap_dn = models.CharField(
|
||||
max_length=1024,
|
||||
default='',
|
||||
)
|
||||
|
||||
|
||||
class UserSessionMembership(BaseModel):
|
||||
"""
|
||||
A lookup table for API session membership given user. Note, there is a
|
||||
|
||||
@@ -66,82 +66,6 @@ def test_awx_task_env_validity(get, patch, admin, value, expected):
|
||||
assert resp.data['AWX_TASK_ENV'] == dict()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_ldap_settings(get, put, patch, delete, admin):
|
||||
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
|
||||
get(url, user=admin, expect=200)
|
||||
# The PUT below will fail at the moment because AUTH_LDAP_GROUP_TYPE
|
||||
# defaults to None but cannot be set to None.
|
||||
# put(url, user=admin, data=response.data, expect=200)
|
||||
delete(url, user=admin, expect=204)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': ''}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldap.example.com'}, expect=400)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldap://ldap.example.com'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldaps://ldap.example.com'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldap://ldap.example.com:389'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldaps://ldap.example.com:636'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldap://ldap.example.com ldap://ldap2.example.com'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldap://ldap.example.com,ldap://ldap2.example.com'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_SERVER_URI': 'ldap://ldap.example.com, ldap://ldap2.example.com'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_BIND_DN': 'cn=Manager,dc=example,dc=com'}, expect=200)
|
||||
patch(url, user=admin, data={'AUTH_LDAP_BIND_DN': u'cn=暴力膜,dc=大新闻,dc=真的粉丝'}, expect=200)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize(
|
||||
'value',
|
||||
[
|
||||
None,
|
||||
'',
|
||||
'INVALID',
|
||||
1,
|
||||
[1],
|
||||
['INVALID'],
|
||||
],
|
||||
)
|
||||
def test_ldap_user_flags_by_group_invalid_dn(get, patch, admin, value):
|
||||
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
|
||||
patch(url, user=admin, data={'AUTH_LDAP_USER_FLAGS_BY_GROUP': {'is_superuser': value}}, expect=400)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_ldap_user_flags_by_group_string(get, patch, admin):
|
||||
expected = 'CN=Admins,OU=Groups,DC=example,DC=com'
|
||||
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
|
||||
patch(url, user=admin, data={'AUTH_LDAP_USER_FLAGS_BY_GROUP': {'is_superuser': expected}}, expect=200)
|
||||
resp = get(url, user=admin)
|
||||
assert resp.data['AUTH_LDAP_USER_FLAGS_BY_GROUP']['is_superuser'] == [expected]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_ldap_user_flags_by_group_list(get, patch, admin):
|
||||
expected = ['CN=Admins,OU=Groups,DC=example,DC=com', 'CN=Superadmins,OU=Groups,DC=example,DC=com']
|
||||
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
|
||||
patch(url, user=admin, data={'AUTH_LDAP_USER_FLAGS_BY_GROUP': {'is_superuser': expected}}, expect=200)
|
||||
resp = get(url, user=admin)
|
||||
assert resp.data['AUTH_LDAP_USER_FLAGS_BY_GROUP']['is_superuser'] == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'setting',
|
||||
[
|
||||
'AUTH_LDAP_USER_DN_TEMPLATE',
|
||||
'AUTH_LDAP_REQUIRE_GROUP',
|
||||
'AUTH_LDAP_DENY_GROUP',
|
||||
],
|
||||
)
|
||||
@pytest.mark.django_db
|
||||
def test_empty_ldap_dn(get, put, patch, delete, admin, setting):
|
||||
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
|
||||
patch(url, user=admin, data={setting: ''}, expect=200)
|
||||
resp = get(url, user=admin, expect=200)
|
||||
assert resp.data[setting] is None
|
||||
|
||||
patch(url, user=admin, data={setting: None}, expect=200)
|
||||
resp = get(url, user=admin, expect=200)
|
||||
assert resp.data[setting] is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_radius_settings(get, put, patch, delete, admin, settings):
|
||||
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'radius'})
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
import ldap
|
||||
import ldif
|
||||
import pytest
|
||||
import os
|
||||
from mockldap import MockLdap
|
||||
|
||||
from awx.api.versioning import reverse
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ldap_generator():
|
||||
def fn(fname, host='localhost'):
|
||||
fh = open(os.path.join(os.path.dirname(os.path.realpath(__file__)), fname), 'rb')
|
||||
ctrl = ldif.LDIFRecordList(fh)
|
||||
ctrl.parse()
|
||||
|
||||
directory = dict(ctrl.all_records)
|
||||
|
||||
mockldap = MockLdap(directory)
|
||||
|
||||
mockldap.start()
|
||||
mockldap['ldap://{}/'.format(host)]
|
||||
|
||||
conn = ldap.initialize('ldap://{}/'.format(host))
|
||||
|
||||
return conn
|
||||
# mockldap.stop()
|
||||
|
||||
return fn
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ldap_settings_generator():
|
||||
def fn(prefix='', dc='ansible', host='ldap.ansible.com'):
|
||||
prefix = '_{}'.format(prefix) if prefix else ''
|
||||
|
||||
data = {
|
||||
'AUTH_LDAP_SERVER_URI': 'ldap://{}'.format(host),
|
||||
'AUTH_LDAP_BIND_DN': 'cn=eng_user1,ou=people,dc={},dc=com'.format(dc),
|
||||
'AUTH_LDAP_BIND_PASSWORD': 'password',
|
||||
"AUTH_LDAP_USER_SEARCH": ["ou=people,dc={},dc=com".format(dc), "SCOPE_SUBTREE", "(cn=%(user)s)"],
|
||||
"AUTH_LDAP_TEAM_MAP": {
|
||||
"LDAP Sales": {"organization": "LDAP Organization", "users": "cn=sales,ou=groups,dc={},dc=com".format(dc), "remove": True},
|
||||
"LDAP IT": {"organization": "LDAP Organization", "users": "cn=it,ou=groups,dc={},dc=com".format(dc), "remove": True},
|
||||
"LDAP Engineering": {"organization": "LDAP Organization", "users": "cn=engineering,ou=groups,dc={},dc=com".format(dc), "remove": True},
|
||||
},
|
||||
"AUTH_LDAP_REQUIRE_GROUP": None,
|
||||
"AUTH_LDAP_USER_ATTR_MAP": {"first_name": "givenName", "last_name": "sn", "email": "mail"},
|
||||
"AUTH_LDAP_GROUP_SEARCH": ["dc={},dc=com".format(dc), "SCOPE_SUBTREE", "(objectClass=groupOfNames)"],
|
||||
"AUTH_LDAP_USER_FLAGS_BY_GROUP": {"is_superuser": "cn=superusers,ou=groups,dc={},dc=com".format(dc)},
|
||||
"AUTH_LDAP_ORGANIZATION_MAP": {
|
||||
"LDAP Organization": {
|
||||
"admins": "cn=engineering_admins,ou=groups,dc={},dc=com".format(dc),
|
||||
"remove_admins": False,
|
||||
"users": [
|
||||
"cn=engineering,ou=groups,dc={},dc=com".format(dc),
|
||||
"cn=sales,ou=groups,dc={},dc=com".format(dc),
|
||||
"cn=it,ou=groups,dc={},dc=com".format(dc),
|
||||
],
|
||||
"remove_users": False,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if prefix:
|
||||
data_new = dict()
|
||||
for k, v in data.items():
|
||||
k_new = k.replace('AUTH_LDAP', 'AUTH_LDAP{}'.format(prefix))
|
||||
data_new[k_new] = v
|
||||
else:
|
||||
data_new = data
|
||||
|
||||
return data_new
|
||||
|
||||
return fn
|
||||
|
||||
|
||||
# Note: mockldap isn't fully featured. Fancy queries aren't fully baked.
|
||||
# However, objects returned are solid so they should flow through django ldap middleware nicely.
|
||||
@pytest.mark.skip(reason="Needs Update - CA")
|
||||
@pytest.mark.django_db
|
||||
def test_login(ldap_generator, patch, post, admin, ldap_settings_generator):
|
||||
auth_url = reverse('api:auth_token_view')
|
||||
ldap_settings_url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
|
||||
|
||||
# Generate mock ldap servers and init with ldap data
|
||||
ldap_generator("../data/ldap_example.ldif", "ldap.example.com")
|
||||
ldap_generator("../data/ldap_redhat.ldif", "ldap.redhat.com")
|
||||
ldap_generator("../data/ldap_ansible.ldif", "ldap.ansible.com")
|
||||
|
||||
ldap_settings_example = ldap_settings_generator(dc='example')
|
||||
ldap_settings_ansible = ldap_settings_generator(prefix='1', dc='ansible')
|
||||
ldap_settings_redhat = ldap_settings_generator(prefix='2', dc='redhat')
|
||||
|
||||
# eng_user1 exists in ansible and redhat but not example
|
||||
patch(ldap_settings_url, user=admin, data=ldap_settings_example, expect=200)
|
||||
|
||||
post(auth_url, data={'username': 'eng_user1', 'password': 'password'}, expect=400)
|
||||
|
||||
patch(ldap_settings_url, user=admin, data=ldap_settings_ansible, expect=200)
|
||||
patch(ldap_settings_url, user=admin, data=ldap_settings_redhat, expect=200)
|
||||
|
||||
post(auth_url, data={'username': 'eng_user1', 'password': 'password'}, expect=200)
|
||||
@@ -28,21 +28,6 @@ settings_dict = {
|
||||
}
|
||||
},
|
||||
"SOCIAL_AUTH_SAML_CALLBACK_URL": "CALLBACK_URL",
|
||||
"AUTH_LDAP_1_SERVER_URI": "SERVER_URI",
|
||||
"AUTH_LDAP_1_BIND_DN": "BIND_DN",
|
||||
"AUTH_LDAP_1_BIND_PASSWORD": "BIND_PASSWORD",
|
||||
"AUTH_LDAP_1_GROUP_SEARCH": ["GROUP_SEARCH"],
|
||||
"AUTH_LDAP_1_GROUP_TYPE": "string object",
|
||||
"AUTH_LDAP_1_GROUP_TYPE_PARAMS": {"member_attr": "member", "name_attr": "cn"},
|
||||
"AUTH_LDAP_1_USER_DN_TEMPLATE": "USER_DN_TEMPLATE",
|
||||
"AUTH_LDAP_1_USER_SEARCH": ["USER_SEARCH"],
|
||||
"AUTH_LDAP_1_USER_ATTR_MAP": {
|
||||
"email": "email",
|
||||
"last_name": "last_name",
|
||||
"first_name": "first_name",
|
||||
},
|
||||
"AUTH_LDAP_1_CONNECTION_OPTIONS": {},
|
||||
"AUTH_LDAP_1_START_TLS": None,
|
||||
}
|
||||
|
||||
|
||||
@@ -93,27 +78,6 @@ class TestDumpAuthConfigCommand(TestCase):
|
||||
"IDP_ATTR_USER_PERMANENT_ID": "name_id",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "ansible_base.authentication.authenticator_plugins.ldap",
|
||||
"name": "LDAP_1",
|
||||
"enabled": True,
|
||||
"create_objects": True,
|
||||
"users_unique": False,
|
||||
"remove_users": True,
|
||||
"configuration": {
|
||||
"SERVER_URI": ["SERVER_URI"],
|
||||
"BIND_DN": "BIND_DN",
|
||||
"BIND_PASSWORD": "BIND_PASSWORD",
|
||||
"CONNECTION_OPTIONS": {},
|
||||
"GROUP_TYPE": "str",
|
||||
"GROUP_TYPE_PARAMS": {"member_attr": "member", "name_attr": "cn"},
|
||||
"GROUP_SEARCH": ["GROUP_SEARCH"],
|
||||
"START_TLS": None,
|
||||
"USER_DN_TEMPLATE": "USER_DN_TEMPLATE",
|
||||
"USER_ATTR_MAP": {"email": "email", "last_name": "last_name", "first_name": "first_name"},
|
||||
"USER_SEARCH": ["USER_SEARCH"],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
def test_json_returned_from_cmd(self):
|
||||
@@ -123,10 +87,3 @@ class TestDumpAuthConfigCommand(TestCase):
|
||||
|
||||
# check configured SAML return
|
||||
assert cmmd_output[0] == self.expected_config[0]
|
||||
|
||||
# check configured LDAP return
|
||||
assert cmmd_output[2] == self.expected_config[1]
|
||||
|
||||
# check unconfigured LDAP return
|
||||
assert "LDAP_0_missing_fields" in cmmd_output[1]
|
||||
assert cmmd_output[1]["LDAP_0_missing_fields"] == ['SERVER_URI', 'GROUP_TYPE', 'GROUP_TYPE_PARAMS', 'USER_DN_TEMPLATE', 'USER_ATTR_MAP']
|
||||
|
||||
Reference in New Issue
Block a user