mirror of
https://github.com/openshift/community.okd.git
synced 2026-05-07 13:42:38 +00:00
* Upgrade Ansible and OKD versions for CI * Use ubi9 and fix sanity * Use correct pip install * Try using quotes * Ensure python3.9 * Upgrade ansible and molecule versions * Remove DeploymentConfig DeploymentConfigs are deprecated and seem to now be causing idempotence problems. Replacing them with Deployments fixes it. * Attempt to fix ldap integration tests Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Move sanity and unit tests to GH actions Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Firt round of sanity fixes Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add kubernetes.core collection as sanity requirement Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add ignore-2.16.txt Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Attempt to fix units Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add ignore-2.17 Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Attempt to fix unit tests Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add pytest-ansible to test-requirements.txt Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add changelog fragment Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add workflow for ansible-lint Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Apply black Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Fix linters Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add # fmt: skip Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Yet another round of linting Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Yet another round of linting Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Remove setup.cfg Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Revert #fmt Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Use ansible-core 2.14 Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Cleanup ansible-lint ignores Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Try using service instead of pod IP * Fix typo * Actually use the correct port * See if NetworkPolicy is preventing connection * using Pod internal IP * fix adm prune auth roles syntax * adding some retry steps * fix: openshift_builds target * add flag --force-with-deps when building downstream collection * Remove yamllint from tox linters, bump minimum python supported version to 3.9, Remove support for ansible-core < 2.14 --------- Signed-off-by: Alina Buzachis <abuzachis@redhat.com> Co-authored-by: Mike Graves <mgraves@redhat.com> Co-authored-by: Alina Buzachis <abuzachis@redhat.com>
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
@@ -24,109 +25,119 @@ LDAP_SEARCH_OUT_OF_SCOPE_ERROR = "trying to search by DN for an entry that exist
|
||||
|
||||
def validate_ldap_sync_config(config):
|
||||
# Validate url
|
||||
url = config.get('url')
|
||||
url = config.get("url")
|
||||
if not url:
|
||||
return "url should be non empty attribute."
|
||||
|
||||
# Make sure bindDN and bindPassword are both set, or both unset
|
||||
bind_dn = config.get('bindDN', "")
|
||||
bind_password = config.get('bindPassword', "")
|
||||
bind_dn = config.get("bindDN", "")
|
||||
bind_password = config.get("bindPassword", "")
|
||||
if (len(bind_dn) == 0) != (len(bind_password) == 0):
|
||||
return "bindDN and bindPassword must both be specified, or both be empty."
|
||||
|
||||
insecure = boolean(config.get('insecure'))
|
||||
ca_file = config.get('ca')
|
||||
insecure = boolean(config.get("insecure"))
|
||||
ca_file = config.get("ca")
|
||||
if insecure:
|
||||
if url.startswith('ldaps://'):
|
||||
if url.startswith("ldaps://"):
|
||||
return "Cannot use ldaps scheme with insecure=true."
|
||||
if ca_file:
|
||||
return "Cannot specify a ca with insecure=true."
|
||||
elif ca_file and not os.path.isfile(ca_file):
|
||||
return "could not read ca file: {0}.".format(ca_file)
|
||||
|
||||
nameMapping = config.get('groupUIDNameMapping', {})
|
||||
nameMapping = config.get("groupUIDNameMapping", {})
|
||||
for k, v in iteritems(nameMapping):
|
||||
if len(k) == 0 or len(v) == 0:
|
||||
return "groupUIDNameMapping has empty key or value"
|
||||
|
||||
schemas = []
|
||||
schema_list = ('rfc2307', 'activeDirectory', 'augmentedActiveDirectory')
|
||||
schema_list = ("rfc2307", "activeDirectory", "augmentedActiveDirectory")
|
||||
for schema in schema_list:
|
||||
if schema in config:
|
||||
schemas.append(schema)
|
||||
|
||||
if len(schemas) == 0:
|
||||
return "No schema-specific config was provided, should be one of %s" % ", ".join(schema_list)
|
||||
return (
|
||||
"No schema-specific config was provided, should be one of %s"
|
||||
% ", ".join(schema_list)
|
||||
)
|
||||
if len(schemas) > 1:
|
||||
return "Exactly one schema-specific config is required; found (%d) %s" % (len(schemas), ','.join(schemas))
|
||||
return "Exactly one schema-specific config is required; found (%d) %s" % (
|
||||
len(schemas),
|
||||
",".join(schemas),
|
||||
)
|
||||
|
||||
if schemas[0] == 'rfc2307':
|
||||
if schemas[0] == "rfc2307":
|
||||
return validate_RFC2307(config.get("rfc2307"))
|
||||
elif schemas[0] == 'activeDirectory':
|
||||
elif schemas[0] == "activeDirectory":
|
||||
return validate_ActiveDirectory(config.get("activeDirectory"))
|
||||
elif schemas[0] == 'augmentedActiveDirectory':
|
||||
elif schemas[0] == "augmentedActiveDirectory":
|
||||
return validate_AugmentedActiveDirectory(config.get("augmentedActiveDirectory"))
|
||||
|
||||
|
||||
def validate_ldap_query(qry, isDNOnly=False):
|
||||
|
||||
# validate query scope
|
||||
scope = qry.get('scope')
|
||||
scope = qry.get("scope")
|
||||
if scope and scope not in ("", "sub", "one", "base"):
|
||||
return "invalid scope %s" % scope
|
||||
|
||||
# validate deref aliases
|
||||
derefAlias = qry.get('derefAliases')
|
||||
derefAlias = qry.get("derefAliases")
|
||||
if derefAlias and derefAlias not in ("never", "search", "base", "always"):
|
||||
return "not a valid LDAP alias dereferncing behavior: %s", derefAlias
|
||||
|
||||
# validate timeout
|
||||
timeout = qry.get('timeout')
|
||||
timeout = qry.get("timeout")
|
||||
if timeout and float(timeout) < 0:
|
||||
return "timeout must be equal to or greater than zero"
|
||||
|
||||
# Validate DN only
|
||||
qry_filter = qry.get('filter', "")
|
||||
qry_filter = qry.get("filter", "")
|
||||
if isDNOnly:
|
||||
if len(qry_filter) > 0:
|
||||
return 'cannot specify a filter when using "dn" as the UID attribute'
|
||||
else:
|
||||
# validate filter
|
||||
if len(qry_filter) == 0 or qry_filter[0] != '(':
|
||||
if len(qry_filter) == 0 or qry_filter[0] != "(":
|
||||
return "filter does not start with an '('"
|
||||
return None
|
||||
|
||||
|
||||
def validate_RFC2307(config):
|
||||
qry = config.get('groupsQuery')
|
||||
qry = config.get("groupsQuery")
|
||||
if not qry or not isinstance(qry, dict):
|
||||
return "RFC2307: groupsQuery requires a dictionary"
|
||||
error = validate_ldap_query(qry)
|
||||
if not error:
|
||||
return error
|
||||
for field in ('groupUIDAttribute', 'groupNameAttributes', 'groupMembershipAttributes',
|
||||
'userUIDAttribute', 'userNameAttributes'):
|
||||
for field in (
|
||||
"groupUIDAttribute",
|
||||
"groupNameAttributes",
|
||||
"groupMembershipAttributes",
|
||||
"userUIDAttribute",
|
||||
"userNameAttributes",
|
||||
):
|
||||
value = config.get(field)
|
||||
if not value:
|
||||
return "RFC2307: {0} is required.".format(field)
|
||||
|
||||
users_qry = config.get('usersQuery')
|
||||
users_qry = config.get("usersQuery")
|
||||
if not users_qry or not isinstance(users_qry, dict):
|
||||
return "RFC2307: usersQuery requires a dictionary"
|
||||
|
||||
isUserDNOnly = (config.get('userUIDAttribute').strip() == 'dn')
|
||||
isUserDNOnly = config.get("userUIDAttribute").strip() == "dn"
|
||||
return validate_ldap_query(users_qry, isDNOnly=isUserDNOnly)
|
||||
|
||||
|
||||
def validate_ActiveDirectory(config, label="ActiveDirectory"):
|
||||
users_qry = config.get('usersQuery')
|
||||
users_qry = config.get("usersQuery")
|
||||
if not users_qry or not isinstance(users_qry, dict):
|
||||
return "{0}: usersQuery requires as dictionnary".format(label)
|
||||
error = validate_ldap_query(users_qry)
|
||||
if not error:
|
||||
return error
|
||||
|
||||
for field in ('userNameAttributes', 'groupMembershipAttributes'):
|
||||
for field in ("userNameAttributes", "groupMembershipAttributes"):
|
||||
value = config.get(field)
|
||||
if not value:
|
||||
return "{0}: {1} is required.".format(field, label)
|
||||
@@ -138,24 +149,24 @@ def validate_AugmentedActiveDirectory(config):
|
||||
error = validate_ActiveDirectory(config, label="AugmentedActiveDirectory")
|
||||
if not error:
|
||||
return error
|
||||
for field in ('groupUIDAttribute', 'groupNameAttributes'):
|
||||
for field in ("groupUIDAttribute", "groupNameAttributes"):
|
||||
value = config.get(field)
|
||||
if not value:
|
||||
return "AugmentedActiveDirectory: {0} is required".format(field)
|
||||
groups_qry = config.get('groupsQuery')
|
||||
groups_qry = config.get("groupsQuery")
|
||||
if not groups_qry or not isinstance(groups_qry, dict):
|
||||
return "AugmentedActiveDirectory: groupsQuery requires as dictionnary."
|
||||
|
||||
isGroupDNOnly = (config.get('groupUIDAttribute').strip() == 'dn')
|
||||
isGroupDNOnly = config.get("groupUIDAttribute").strip() == "dn"
|
||||
return validate_ldap_query(groups_qry, isDNOnly=isGroupDNOnly)
|
||||
|
||||
|
||||
def determine_ldap_scope(scope):
|
||||
if scope in ("", "sub"):
|
||||
return ldap.SCOPE_SUBTREE
|
||||
elif scope == 'base':
|
||||
elif scope == "base":
|
||||
return ldap.SCOPE_BASE
|
||||
elif scope == 'one':
|
||||
elif scope == "one":
|
||||
return ldap.SCOPE_ONELEVEL
|
||||
return None
|
||||
|
||||
@@ -175,28 +186,28 @@ def determine_deref_aliases(derefAlias):
|
||||
|
||||
def openshift_ldap_build_base_query(config):
|
||||
qry = {}
|
||||
if config.get('baseDN'):
|
||||
qry['base'] = config.get('baseDN')
|
||||
if config.get("baseDN"):
|
||||
qry["base"] = config.get("baseDN")
|
||||
|
||||
scope = determine_ldap_scope(config.get('scope'))
|
||||
scope = determine_ldap_scope(config.get("scope"))
|
||||
if scope:
|
||||
qry['scope'] = scope
|
||||
qry["scope"] = scope
|
||||
|
||||
pageSize = config.get('pageSize')
|
||||
pageSize = config.get("pageSize")
|
||||
if pageSize and int(pageSize) > 0:
|
||||
qry['sizelimit'] = int(pageSize)
|
||||
qry["sizelimit"] = int(pageSize)
|
||||
|
||||
timeout = config.get('timeout')
|
||||
timeout = config.get("timeout")
|
||||
if timeout and int(timeout) > 0:
|
||||
qry['timeout'] = int(timeout)
|
||||
qry["timeout"] = int(timeout)
|
||||
|
||||
filter = config.get('filter')
|
||||
filter = config.get("filter")
|
||||
if filter:
|
||||
qry['filterstr'] = filter
|
||||
qry["filterstr"] = filter
|
||||
|
||||
derefAlias = determine_deref_aliases(config.get('derefAliases'))
|
||||
derefAlias = determine_deref_aliases(config.get("derefAliases"))
|
||||
if derefAlias:
|
||||
qry['derefAlias'] = derefAlias
|
||||
qry["derefAlias"] = derefAlias
|
||||
return qry
|
||||
|
||||
|
||||
@@ -205,32 +216,30 @@ def openshift_ldap_get_attribute_for_entry(entry, attribute):
|
||||
if isinstance(attribute, list):
|
||||
attributes = attribute
|
||||
for k in attributes:
|
||||
if k.lower() == 'dn':
|
||||
if k.lower() == "dn":
|
||||
return entry[0]
|
||||
v = entry[1].get(k, None)
|
||||
if v:
|
||||
if isinstance(v, list):
|
||||
result = []
|
||||
for x in v:
|
||||
if hasattr(x, 'decode'):
|
||||
result.append(x.decode('utf-8'))
|
||||
if hasattr(x, "decode"):
|
||||
result.append(x.decode("utf-8"))
|
||||
else:
|
||||
result.append(x)
|
||||
return result
|
||||
else:
|
||||
return v.decode('utf-8') if hasattr(v, 'decode') else v
|
||||
return v.decode("utf-8") if hasattr(v, "decode") else v
|
||||
return ""
|
||||
|
||||
|
||||
def ldap_split_host_port(hostport):
|
||||
"""
|
||||
ldap_split_host_port splits a network address of the form "host:port",
|
||||
"host%zone:port", "[host]:port" or "[host%zone]:port" into host or
|
||||
host%zone and port.
|
||||
ldap_split_host_port splits a network address of the form "host:port",
|
||||
"host%zone:port", "[host]:port" or "[host%zone]:port" into host or
|
||||
host%zone and port.
|
||||
"""
|
||||
result = dict(
|
||||
scheme=None, netlocation=None, host=None, port=None
|
||||
)
|
||||
result = dict(scheme=None, netlocation=None, host=None, port=None)
|
||||
if not hostport:
|
||||
return result, None
|
||||
|
||||
@@ -240,10 +249,10 @@ def ldap_split_host_port(hostport):
|
||||
if "://" in hostport:
|
||||
idx = hostport.find(scheme_l)
|
||||
result["scheme"] = hostport[:idx]
|
||||
netlocation = hostport[idx + len(scheme_l):]
|
||||
netlocation = hostport[idx + len(scheme_l):] # fmt: skip
|
||||
result["netlocation"] = netlocation
|
||||
|
||||
if netlocation[-1] == ']':
|
||||
if netlocation[-1] == "]":
|
||||
# ipv6 literal (with no port)
|
||||
result["host"] = netlocation
|
||||
|
||||
@@ -259,21 +268,32 @@ def ldap_split_host_port(hostport):
|
||||
|
||||
def openshift_ldap_query_for_entries(connection, qry, unique_entry=True):
|
||||
# set deref alias (TODO: need to set a default value to reset for each transaction)
|
||||
derefAlias = qry.pop('derefAlias', None)
|
||||
derefAlias = qry.pop("derefAlias", None)
|
||||
if derefAlias:
|
||||
ldap.set_option(ldap.OPT_DEREF, derefAlias)
|
||||
try:
|
||||
result = connection.search_ext_s(**qry)
|
||||
if not result or len(result) == 0:
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(qry['base'], qry['filterstr'])
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(
|
||||
qry["base"], qry["filterstr"]
|
||||
)
|
||||
if len(result) > 1 and unique_entry:
|
||||
if qry.get('scope') == ldap.SCOPE_BASE:
|
||||
return None, "multiple entries found matching dn={0}: {1}".format(qry['base'], result)
|
||||
if qry.get("scope") == ldap.SCOPE_BASE:
|
||||
return None, "multiple entries found matching dn={0}: {1}".format(
|
||||
qry["base"], result
|
||||
)
|
||||
else:
|
||||
return None, "multiple entries found matching filter {0}: {1}".format(qry['filterstr'], result)
|
||||
return None, "multiple entries found matching filter {0}: {1}".format(
|
||||
qry["filterstr"], result
|
||||
)
|
||||
return result, None
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
return None, "search for entry with base dn='{0}' refers to a non-existent entry".format(qry['base'])
|
||||
return (
|
||||
None,
|
||||
"search for entry with base dn='{0}' refers to a non-existent entry".format(
|
||||
qry["base"]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def openshift_equal_dn_objects(dn_obj, other_dn_obj):
|
||||
@@ -303,7 +323,9 @@ def openshift_ancestorof_dn(dn, other):
|
||||
if len(dn_obj) >= len(other_dn_obj):
|
||||
return False
|
||||
# Take the last attribute from the other DN to compare against
|
||||
return openshift_equal_dn_objects(dn_obj, other_dn_obj[len(other_dn_obj) - len(dn_obj):])
|
||||
return openshift_equal_dn_objects(
|
||||
dn_obj, other_dn_obj[len(other_dn_obj) - len(dn_obj):] # fmt: skip
|
||||
)
|
||||
|
||||
|
||||
class OpenshiftLDAPQueryOnAttribute(object):
|
||||
@@ -324,33 +346,38 @@ class OpenshiftLDAPQueryOnAttribute(object):
|
||||
output = []
|
||||
hex_string = "0123456789abcdef"
|
||||
for c in buffer:
|
||||
if ord(c) > 0x7f or c in ('(', ')', '\\', '*') or c == 0:
|
||||
if ord(c) > 0x7F or c in ("(", ")", "\\", "*") or c == 0:
|
||||
first = ord(c) >> 4
|
||||
second = ord(c) & 0xf
|
||||
output += ['\\', hex_string[first], hex_string[second]]
|
||||
second = ord(c) & 0xF
|
||||
output += ["\\", hex_string[first], hex_string[second]]
|
||||
else:
|
||||
output.append(c)
|
||||
return ''.join(output)
|
||||
return "".join(output)
|
||||
|
||||
def build_request(self, ldapuid, attributes):
|
||||
params = copy.deepcopy(self.qry)
|
||||
if self.query_attribute.lower() == 'dn':
|
||||
if self.query_attribute.lower() == "dn":
|
||||
if ldapuid:
|
||||
if not openshift_equal_dn(ldapuid, params['base']) and not openshift_ancestorof_dn(params['base'], ldapuid):
|
||||
if not openshift_equal_dn(
|
||||
ldapuid, params["base"]
|
||||
) and not openshift_ancestorof_dn(params["base"], ldapuid):
|
||||
return None, LDAP_SEARCH_OUT_OF_SCOPE_ERROR
|
||||
params['base'] = ldapuid
|
||||
params['scope'] = ldap.SCOPE_BASE
|
||||
params["base"] = ldapuid
|
||||
params["scope"] = ldap.SCOPE_BASE
|
||||
# filter that returns all values
|
||||
params['filterstr'] = "(objectClass=*)"
|
||||
params['attrlist'] = attributes
|
||||
params["filterstr"] = "(objectClass=*)"
|
||||
params["attrlist"] = attributes
|
||||
else:
|
||||
# Builds the query containing a filter that conjoins the common filter given
|
||||
# in the configuration with the specific attribute filter for which the attribute value is given
|
||||
specificFilter = "%s=%s" % (self.escape_filter(self.query_attribute), self.escape_filter(ldapuid))
|
||||
qry_filter = params.get('filterstr', None)
|
||||
specificFilter = "%s=%s" % (
|
||||
self.escape_filter(self.query_attribute),
|
||||
self.escape_filter(ldapuid),
|
||||
)
|
||||
qry_filter = params.get("filterstr", None)
|
||||
if qry_filter:
|
||||
params['filterstr'] = "(&%s(%s))" % (qry_filter, specificFilter)
|
||||
params['attrlist'] = attributes
|
||||
params["filterstr"] = "(&%s(%s))" % (qry_filter, specificFilter)
|
||||
params["attrlist"] = attributes
|
||||
return params, None
|
||||
|
||||
def ldap_search(self, connection, ldapuid, required_attributes, unique_entry=True):
|
||||
@@ -358,21 +385,29 @@ class OpenshiftLDAPQueryOnAttribute(object):
|
||||
if error:
|
||||
return None, error
|
||||
# set deref alias (TODO: need to set a default value to reset for each transaction)
|
||||
derefAlias = query.pop('derefAlias', None)
|
||||
derefAlias = query.pop("derefAlias", None)
|
||||
if derefAlias:
|
||||
ldap.set_option(ldap.OPT_DEREF, derefAlias)
|
||||
|
||||
try:
|
||||
result = connection.search_ext_s(**query)
|
||||
if not result or len(result) == 0:
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(query['base'], query['filterstr'])
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(
|
||||
query["base"], query["filterstr"]
|
||||
)
|
||||
if unique_entry:
|
||||
if len(result) > 1:
|
||||
return None, "Multiple Entries found matching search criteria: %s (%s)" % (query, result)
|
||||
return (
|
||||
None,
|
||||
"Multiple Entries found matching search criteria: %s (%s)"
|
||||
% (query, result),
|
||||
)
|
||||
result = result[0]
|
||||
return result, None
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(query['base'], query['filterstr'])
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(
|
||||
query["base"], query["filterstr"]
|
||||
)
|
||||
except Exception as err:
|
||||
return None, "Request %s failed due to: %s" % (query, err)
|
||||
|
||||
@@ -384,30 +419,43 @@ class OpenshiftLDAPQuery(object):
|
||||
|
||||
def build_request(self, attributes):
|
||||
params = copy.deepcopy(self.qry)
|
||||
params['attrlist'] = attributes
|
||||
params["attrlist"] = attributes
|
||||
return params
|
||||
|
||||
def ldap_search(self, connection, required_attributes):
|
||||
query = self.build_request(required_attributes)
|
||||
# set deref alias (TODO: need to set a default value to reset for each transaction)
|
||||
derefAlias = query.pop('derefAlias', None)
|
||||
derefAlias = query.pop("derefAlias", None)
|
||||
if derefAlias:
|
||||
ldap.set_option(ldap.OPT_DEREF, derefAlias)
|
||||
|
||||
try:
|
||||
result = connection.search_ext_s(**query)
|
||||
if not result or len(result) == 0:
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(query['base'], query['filterstr'])
|
||||
return None, "Entry not found for base='{0}' and filter='{1}'".format(
|
||||
query["base"], query["filterstr"]
|
||||
)
|
||||
return result, None
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
return None, "search for entry with base dn='{0}' refers to a non-existent entry".format(query['base'])
|
||||
return (
|
||||
None,
|
||||
"search for entry with base dn='{0}' refers to a non-existent entry".format(
|
||||
query["base"]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class OpenshiftLDAPInterface(object):
|
||||
|
||||
def __init__(self, connection, groupQuery, groupNameAttributes, groupMembershipAttributes,
|
||||
userQuery, userNameAttributes, config):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
connection,
|
||||
groupQuery,
|
||||
groupNameAttributes,
|
||||
groupMembershipAttributes,
|
||||
userQuery,
|
||||
userNameAttributes,
|
||||
config,
|
||||
):
|
||||
self.connection = connection
|
||||
self.groupQuery = copy.deepcopy(groupQuery)
|
||||
self.groupNameAttributes = groupNameAttributes
|
||||
@@ -416,8 +464,12 @@ class OpenshiftLDAPInterface(object):
|
||||
self.userNameAttributes = userNameAttributes
|
||||
self.config = config
|
||||
|
||||
self.tolerate_not_found = boolean(config.get('tolerateMemberNotFoundErrors', False))
|
||||
self.tolerate_out_of_scope = boolean(config.get('tolerateMemberOutOfScopeErrors', False))
|
||||
self.tolerate_not_found = boolean(
|
||||
config.get("tolerateMemberNotFoundErrors", False)
|
||||
)
|
||||
self.tolerate_out_of_scope = boolean(
|
||||
config.get("tolerateMemberOutOfScopeErrors", False)
|
||||
)
|
||||
|
||||
self.required_group_attributes = [self.groupQuery.query_attribute]
|
||||
for x in self.groupNameAttributes + self.groupMembershipAttributes:
|
||||
@@ -434,13 +486,15 @@ class OpenshiftLDAPInterface(object):
|
||||
|
||||
def get_group_entry(self, uid):
|
||||
"""
|
||||
get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
|
||||
of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
|
||||
get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
|
||||
of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
|
||||
"""
|
||||
if uid in self.cached_groups:
|
||||
return self.cached_groups.get(uid), None
|
||||
|
||||
group, err = self.groupQuery.ldap_search(self.connection, uid, self.required_group_attributes)
|
||||
group, err = self.groupQuery.ldap_search(
|
||||
self.connection, uid, self.required_group_attributes
|
||||
)
|
||||
if err:
|
||||
return None, err
|
||||
self.cached_groups[uid] = group
|
||||
@@ -448,13 +502,15 @@ class OpenshiftLDAPInterface(object):
|
||||
|
||||
def get_user_entry(self, uid):
|
||||
"""
|
||||
get_user_entry returns an LDAP group entry for the given user UID by searching the internal cache
|
||||
of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
|
||||
get_user_entry returns an LDAP group entry for the given user UID by searching the internal cache
|
||||
of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
|
||||
"""
|
||||
if uid in self.cached_users:
|
||||
return self.cached_users.get(uid), None
|
||||
|
||||
entry, err = self.userQuery.ldap_search(self.connection, uid, self.required_user_attributes)
|
||||
entry, err = self.userQuery.ldap_search(
|
||||
self.connection, uid, self.required_user_attributes
|
||||
)
|
||||
if err:
|
||||
return None, err
|
||||
self.cached_users[uid] = entry
|
||||
@@ -466,19 +522,19 @@ class OpenshiftLDAPInterface(object):
|
||||
|
||||
def list_groups(self):
|
||||
group_qry = copy.deepcopy(self.groupQuery.qry)
|
||||
group_qry['attrlist'] = self.required_group_attributes
|
||||
group_qry["attrlist"] = self.required_group_attributes
|
||||
|
||||
groups, err = openshift_ldap_query_for_entries(
|
||||
connection=self.connection,
|
||||
qry=group_qry,
|
||||
unique_entry=False
|
||||
connection=self.connection, qry=group_qry, unique_entry=False
|
||||
)
|
||||
if err:
|
||||
return None, err
|
||||
|
||||
group_uids = []
|
||||
for entry in groups:
|
||||
uid = openshift_ldap_get_attribute_for_entry(entry, self.groupQuery.query_attribute)
|
||||
uid = openshift_ldap_get_attribute_for_entry(
|
||||
entry, self.groupQuery.query_attribute
|
||||
)
|
||||
if not uid:
|
||||
return None, "Unable to find LDAP group uid for entry %s" % entry
|
||||
self.cached_groups[uid] = entry
|
||||
@@ -487,7 +543,7 @@ class OpenshiftLDAPInterface(object):
|
||||
|
||||
def extract_members(self, uid):
|
||||
"""
|
||||
returns the LDAP member entries for a group specified with a ldapGroupUID
|
||||
returns the LDAP member entries for a group specified with a ldapGroupUID
|
||||
"""
|
||||
# Get group entry from LDAP
|
||||
group, err = self.get_group_entry(uid)
|
||||
@@ -514,39 +570,46 @@ class OpenshiftLDAPInterface(object):
|
||||
|
||||
|
||||
class OpenshiftLDAPRFC2307(object):
|
||||
|
||||
def __init__(self, config, ldap_connection):
|
||||
|
||||
self.config = config
|
||||
self.ldap_interface = self.create_ldap_interface(ldap_connection)
|
||||
|
||||
def create_ldap_interface(self, connection):
|
||||
segment = self.config.get("rfc2307")
|
||||
groups_base_qry = openshift_ldap_build_base_query(segment['groupsQuery'])
|
||||
users_base_qry = openshift_ldap_build_base_query(segment['usersQuery'])
|
||||
groups_base_qry = openshift_ldap_build_base_query(segment["groupsQuery"])
|
||||
users_base_qry = openshift_ldap_build_base_query(segment["usersQuery"])
|
||||
|
||||
groups_query = OpenshiftLDAPQueryOnAttribute(groups_base_qry, segment['groupUIDAttribute'])
|
||||
users_query = OpenshiftLDAPQueryOnAttribute(users_base_qry, segment['userUIDAttribute'])
|
||||
groups_query = OpenshiftLDAPQueryOnAttribute(
|
||||
groups_base_qry, segment["groupUIDAttribute"]
|
||||
)
|
||||
users_query = OpenshiftLDAPQueryOnAttribute(
|
||||
users_base_qry, segment["userUIDAttribute"]
|
||||
)
|
||||
|
||||
params = dict(
|
||||
connection=connection,
|
||||
groupQuery=groups_query,
|
||||
groupNameAttributes=segment['groupNameAttributes'],
|
||||
groupMembershipAttributes=segment['groupMembershipAttributes'],
|
||||
groupNameAttributes=segment["groupNameAttributes"],
|
||||
groupMembershipAttributes=segment["groupMembershipAttributes"],
|
||||
userQuery=users_query,
|
||||
userNameAttributes=segment['userNameAttributes'],
|
||||
config=segment
|
||||
userNameAttributes=segment["userNameAttributes"],
|
||||
config=segment,
|
||||
)
|
||||
return OpenshiftLDAPInterface(**params)
|
||||
|
||||
def get_username_for_entry(self, entry):
|
||||
username = openshift_ldap_get_attribute_for_entry(entry, self.ldap_interface.userNameAttributes)
|
||||
username = openshift_ldap_get_attribute_for_entry(
|
||||
entry, self.ldap_interface.userNameAttributes
|
||||
)
|
||||
if not username:
|
||||
return None, "The user entry (%s) does not map to a OpenShift User name with the given mapping" % entry
|
||||
return (
|
||||
None,
|
||||
"The user entry (%s) does not map to a OpenShift User name with the given mapping"
|
||||
% entry,
|
||||
)
|
||||
return username, None
|
||||
|
||||
def get_group_name_for_uid(self, uid):
|
||||
|
||||
# Get name from User defined mapping
|
||||
groupuid_name_mapping = self.config.get("groupUIDNameMapping")
|
||||
if groupuid_name_mapping and uid in groupuid_name_mapping:
|
||||
@@ -555,10 +618,13 @@ class OpenshiftLDAPRFC2307(object):
|
||||
group, err = self.ldap_interface.get_group_entry(uid)
|
||||
if err:
|
||||
return None, err
|
||||
group_name = openshift_ldap_get_attribute_for_entry(group, self.ldap_interface.groupNameAttributes)
|
||||
group_name = openshift_ldap_get_attribute_for_entry(
|
||||
group, self.ldap_interface.groupNameAttributes
|
||||
)
|
||||
if not group_name:
|
||||
error = "The group entry (%s) does not map to an OpenShift Group name with the given name attribute (%s)" % (
|
||||
group, self.ldap_interface.groupNameAttributes
|
||||
error = (
|
||||
"The group entry (%s) does not map to an OpenShift Group name with the given name attribute (%s)"
|
||||
% (group, self.ldap_interface.groupNameAttributes)
|
||||
)
|
||||
return None, error
|
||||
if isinstance(group_name, list):
|
||||
@@ -570,7 +636,11 @@ class OpenshiftLDAPRFC2307(object):
|
||||
def is_ldapgroup_exists(self, uid):
|
||||
group, err = self.ldap_interface.get_group_entry(uid)
|
||||
if err:
|
||||
if err == LDAP_SEARCH_OUT_OF_SCOPE_ERROR or err.startswith("Entry not found") or "non-existent entry" in err:
|
||||
if (
|
||||
err == LDAP_SEARCH_OUT_OF_SCOPE_ERROR
|
||||
or err.startswith("Entry not found")
|
||||
or "non-existent entry" in err
|
||||
):
|
||||
return False, None
|
||||
return False, err
|
||||
if group:
|
||||
@@ -585,7 +655,6 @@ class OpenshiftLDAPRFC2307(object):
|
||||
|
||||
|
||||
class OpenshiftLDAP_ADInterface(object):
|
||||
|
||||
def __init__(self, connection, user_query, group_member_attr, user_name_attr):
|
||||
self.connection = connection
|
||||
self.userQuery = user_query
|
||||
@@ -609,7 +678,9 @@ class OpenshiftLDAP_ADInterface(object):
|
||||
def populate_cache(self):
|
||||
if not self.cache_populated:
|
||||
self.cache_populated = True
|
||||
entries, err = self.userQuery.ldap_search(self.connection, self.required_user_attributes)
|
||||
entries, err = self.userQuery.ldap_search(
|
||||
self.connection, self.required_user_attributes
|
||||
)
|
||||
if err:
|
||||
return err
|
||||
|
||||
@@ -645,7 +716,9 @@ class OpenshiftLDAP_ADInterface(object):
|
||||
users_in_group = []
|
||||
for attr in self.groupMembershipAttributes:
|
||||
query_on_attribute = OpenshiftLDAPQueryOnAttribute(self.userQuery.qry, attr)
|
||||
entries, error = query_on_attribute.ldap_search(self.connection, uid, self.required_user_attributes, unique_entry=False)
|
||||
entries, error = query_on_attribute.ldap_search(
|
||||
self.connection, uid, self.required_user_attributes, unique_entry=False
|
||||
)
|
||||
if error and "not found" not in error:
|
||||
return None, error
|
||||
if not entries:
|
||||
@@ -660,15 +733,13 @@ class OpenshiftLDAP_ADInterface(object):
|
||||
|
||||
|
||||
class OpenshiftLDAPActiveDirectory(object):
|
||||
|
||||
def __init__(self, config, ldap_connection):
|
||||
|
||||
self.config = config
|
||||
self.ldap_interface = self.create_ldap_interface(ldap_connection)
|
||||
|
||||
def create_ldap_interface(self, connection):
|
||||
segment = self.config.get("activeDirectory")
|
||||
base_query = openshift_ldap_build_base_query(segment['usersQuery'])
|
||||
base_query = openshift_ldap_build_base_query(segment["usersQuery"])
|
||||
user_query = OpenshiftLDAPQuery(base_query)
|
||||
|
||||
return OpenshiftLDAP_ADInterface(
|
||||
@@ -679,9 +750,15 @@ class OpenshiftLDAPActiveDirectory(object):
|
||||
)
|
||||
|
||||
def get_username_for_entry(self, entry):
|
||||
username = openshift_ldap_get_attribute_for_entry(entry, self.ldap_interface.userNameAttributes)
|
||||
username = openshift_ldap_get_attribute_for_entry(
|
||||
entry, self.ldap_interface.userNameAttributes
|
||||
)
|
||||
if not username:
|
||||
return None, "The user entry (%s) does not map to a OpenShift User name with the given mapping" % entry
|
||||
return (
|
||||
None,
|
||||
"The user entry (%s) does not map to a OpenShift User name with the given mapping"
|
||||
% entry,
|
||||
)
|
||||
return username, None
|
||||
|
||||
def get_group_name_for_uid(self, uid):
|
||||
@@ -702,8 +779,15 @@ class OpenshiftLDAPActiveDirectory(object):
|
||||
|
||||
|
||||
class OpenshiftLDAP_AugmentedADInterface(OpenshiftLDAP_ADInterface):
|
||||
|
||||
def __init__(self, connection, user_query, group_member_attr, user_name_attr, group_qry, group_name_attr):
|
||||
def __init__(
|
||||
self,
|
||||
connection,
|
||||
user_query,
|
||||
group_member_attr,
|
||||
user_name_attr,
|
||||
group_qry,
|
||||
group_name_attr,
|
||||
):
|
||||
super(OpenshiftLDAP_AugmentedADInterface, self).__init__(
|
||||
connection, user_query, group_member_attr, user_name_attr
|
||||
)
|
||||
@@ -719,13 +803,15 @@ class OpenshiftLDAP_AugmentedADInterface(OpenshiftLDAP_ADInterface):
|
||||
|
||||
def get_group_entry(self, uid):
|
||||
"""
|
||||
get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
|
||||
of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
|
||||
get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
|
||||
of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
|
||||
"""
|
||||
if uid in self.cached_groups:
|
||||
return self.cached_groups.get(uid), None
|
||||
|
||||
group, err = self.groupQuery.ldap_search(self.connection, uid, self.required_group_attributes)
|
||||
group, err = self.groupQuery.ldap_search(
|
||||
self.connection, uid, self.required_group_attributes
|
||||
)
|
||||
if err:
|
||||
return None, err
|
||||
self.cached_groups[uid] = group
|
||||
@@ -750,19 +836,19 @@ class OpenshiftLDAP_AugmentedADInterface(OpenshiftLDAP_ADInterface):
|
||||
|
||||
|
||||
class OpenshiftLDAPAugmentedActiveDirectory(OpenshiftLDAPRFC2307):
|
||||
|
||||
def __init__(self, config, ldap_connection):
|
||||
|
||||
self.config = config
|
||||
self.ldap_interface = self.create_ldap_interface(ldap_connection)
|
||||
|
||||
def create_ldap_interface(self, connection):
|
||||
segment = self.config.get("augmentedActiveDirectory")
|
||||
user_base_query = openshift_ldap_build_base_query(segment['usersQuery'])
|
||||
groups_base_qry = openshift_ldap_build_base_query(segment['groupsQuery'])
|
||||
user_base_query = openshift_ldap_build_base_query(segment["usersQuery"])
|
||||
groups_base_qry = openshift_ldap_build_base_query(segment["groupsQuery"])
|
||||
|
||||
user_query = OpenshiftLDAPQuery(user_base_query)
|
||||
groups_query = OpenshiftLDAPQueryOnAttribute(groups_base_qry, segment['groupUIDAttribute'])
|
||||
groups_query = OpenshiftLDAPQueryOnAttribute(
|
||||
groups_base_qry, segment["groupUIDAttribute"]
|
||||
)
|
||||
|
||||
return OpenshiftLDAP_AugmentedADInterface(
|
||||
connection=connection,
|
||||
@@ -770,7 +856,7 @@ class OpenshiftLDAPAugmentedActiveDirectory(OpenshiftLDAPRFC2307):
|
||||
group_member_attr=segment["groupMembershipAttributes"],
|
||||
user_name_attr=segment["userNameAttributes"],
|
||||
group_qry=groups_query,
|
||||
group_name_attr=segment["groupNameAttributes"]
|
||||
group_name_attr=segment["groupNameAttributes"],
|
||||
)
|
||||
|
||||
def is_ldapgroup_exists(self, uid):
|
||||
|
||||
Reference in New Issue
Block a user