diff --git a/awx/__init__.py b/awx/__init__.py index d506b6f1c0..e3cb8020b1 100644 --- a/awx/__init__.py +++ b/awx/__init__.py @@ -6,7 +6,7 @@ import sys import warnings import site -__version__ = '2.4.2' +__version__ = '2.4.3' __all__ = ['__version__'] diff --git a/awx/main/tests/users.py b/awx/main/tests/users.py index 322c73c522..5cea474875 100644 --- a/awx/main/tests/users.py +++ b/awx/main/tests/users.py @@ -929,7 +929,7 @@ class LdapTest(BaseTest): if not self.ldap_password: self.skipTest('no test LDAP password defined') # Set test LDAP settings that are always needed. - for name in ('SERVER_URI', 'BIND_DN', 'BIND_PASSWORD', 'USE_TLS'): + for name in ('SERVER_URI', 'BIND_DN', 'BIND_PASSWORD', 'USE_TLS', 'CONNECTION_OPTIONS'): self.use_test_setting(name) def check_login(self, username=None, password=None, should_fail=False): diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 6733f0d408..d61f0fac10 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -4,6 +4,7 @@ import os import re # noqa import sys +import ldap import djcelery from datetime import timedelta @@ -231,6 +232,12 @@ AUTHENTICATION_BACKENDS = ( # LDAP server (default to None to skip using LDAP authentication). AUTH_LDAP_SERVER_URI = None +# Disable LDAP referrals by default (to prevent certain LDAP queries from +# hanging with AD). +AUTH_LDAP_CONNECTION_OPTIONS = { + ldap.OPT_REFERRALS: 0, +} + # Radius server settings (default to empty string to skip using Radius auth). RADIUS_SERVER = '' RADIUS_PORT = 1812 diff --git a/awx/settings/local_settings.py.docker_compose b/awx/settings/local_settings.py.docker_compose index 172eeccb91..905e26857f 100644 --- a/awx/settings/local_settings.py.docker_compose +++ b/awx/settings/local_settings.py.docker_compose @@ -167,6 +167,11 @@ LOGGING['handlers']['syslog'] = { # Refer to django-auth-ldap docs for more details: # http://pythonhosted.org/django-auth-ldap/authentication.html +# Imports needed for LDAP configuration. +import ldap +from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion +from django_auth_ldap.config import ActiveDirectoryGroupType + # LDAP server URI, such as "ldap://ldap.example.com:389" (non-SSL) or # "ldaps://ldap.example.com:636" (SSL). LDAP authentication is disable if this # parameter is empty. @@ -183,10 +188,11 @@ AUTH_LDAP_BIND_PASSWORD = '' # Enable TLS when the connection is not using SSL. AUTH_LDAP_START_TLS = False -# Imports needed for remaining LDAP configuration. -import ldap -from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion -from django_auth_ldap.config import ActiveDirectoryGroupType +# Additional options to set for the LDAP connection. LDAP referrals are +# disabled by default (to prevent certain LDAP queries from hanging with AD). +AUTH_LDAP_CONNECTION_OPTIONS = { + ldap.OPT_REFERRALS: 0, +} # LDAP search query to find users. AUTH_LDAP_USER_SEARCH = LDAPSearch( @@ -334,6 +340,9 @@ TEST_AUTH_LDAP_SERVER_URI = '' TEST_AUTH_LDAP_BIND_DN = '' TEST_AUTH_LDAP_BIND_PASSWORD = '' TEST_AUTH_LDAP_START_TLS = False +TEST_AUTH_LDAP_CONNECTION_OPTIONS = { + ldap.OPT_REFERRALS: 0, +} # LDAP username/password for testing authentication. TEST_AUTH_LDAP_USERNAME = '' diff --git a/awx/settings/local_settings.py.example b/awx/settings/local_settings.py.example index ad41c27600..2fb0c745fc 100644 --- a/awx/settings/local_settings.py.example +++ b/awx/settings/local_settings.py.example @@ -165,6 +165,11 @@ LOGGING['handlers']['syslog'] = { # Refer to django-auth-ldap docs for more details: # http://pythonhosted.org/django-auth-ldap/authentication.html +# Imports needed for LDAP configuration. +import ldap +from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion +from django_auth_ldap.config import ActiveDirectoryGroupType + # LDAP server URI, such as "ldap://ldap.example.com:389" (non-SSL) or # "ldaps://ldap.example.com:636" (SSL). LDAP authentication is disable if this # parameter is empty. @@ -181,10 +186,11 @@ AUTH_LDAP_BIND_PASSWORD = '' # Enable TLS when the connection is not using SSL. AUTH_LDAP_START_TLS = False -# Imports needed for remaining LDAP configuration. -import ldap -from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion -from django_auth_ldap.config import ActiveDirectoryGroupType +# Additional options to set for the LDAP connection. LDAP referrals are +# disabled by default (to prevent certain LDAP queries from hanging with AD). +AUTH_LDAP_CONNECTION_OPTIONS = { + ldap.OPT_REFERRALS: 0, +} # LDAP search query to find users. AUTH_LDAP_USER_SEARCH = LDAPSearch( @@ -332,6 +338,9 @@ TEST_AUTH_LDAP_SERVER_URI = '' TEST_AUTH_LDAP_BIND_DN = '' TEST_AUTH_LDAP_BIND_PASSWORD = '' TEST_AUTH_LDAP_START_TLS = False +TEST_AUTH_LDAP_CONNECTION_OPTIONS = { + ldap.OPT_REFERRALS: 0, +} # LDAP username/password for testing authentication. TEST_AUTH_LDAP_USERNAME = '' diff --git a/awx/sso/backends.py b/awx/sso/backends.py index d033fcab9b..b2c11be2d6 100644 --- a/awx/sso/backends.py +++ b/awx/sso/backends.py @@ -199,6 +199,10 @@ def on_populate_user(sender, **kwargs): ldap_user = kwargs['ldap_user'] backend = ldap_user.backend + # Prefetch user's groups to prevent LDAP queries for each org/team when + # checking membership. + ldap_user._get_groups().get_group_dns() + # Update organization membership based on group memberships. org_map = getattr(backend.settings, 'ORGANIZATION_MAP', {}) for org_name, org_opts in org_map.items(): diff --git a/awx/ui/client/src/controllers/JobTemplates.js b/awx/ui/client/src/controllers/JobTemplates.js index f1dc484dbd..b8ea1bd888 100644 --- a/awx/ui/client/src/controllers/JobTemplates.js +++ b/awx/ui/client/src/controllers/JobTemplates.js @@ -903,7 +903,7 @@ export function JobTemplatesEdit($filter, $scope, $rootScope, $compile, $locatio $scope.search(relatedSets[set].iterator); } - dft = ($scope.host_config_key === "" || $scope.host_config_key === null) ? 'false' : 'true'; + dft = ($scope.host_config_key === "" || $scope.host_config_key === null) ? false : true; md5Setup({ scope: $scope, master: master,