Skip to content

Added the ability to pull alternative ldap attributes for givenName, sn and c #321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions examples/config files - basic/3 connector-ldap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,36 @@ user_email_format: "{mail}"
# produce a unique username for each user.
#user_username_format: "{department}_{user_id}"

# (optional) user_given_name_format (default value given below)
# user_given_name_format specifies how to construct a user's given name by
# combining constant strings with the values of specific directory attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value used here is simple, and suitable for OpenLDAP systems.
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
#user_given_name_format: "{givenName}"

# (optional) user_surname_format (default value given below)
# user_surname_format specifies how to construct a user's surname by
# combining constant strings with the values of specific directory attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value used here is simple, and suitable for OpenLDAP systems.
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
#user_surname_format: "{sn}"

# (optional) user_country_code_format (default value given below)
# user_country_code_format specifies how to construct a user's country code by
# combining constant strings with the values of specific directory attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value used here is simple, and suitable for OpenLDAP systems.
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
#user_country_code_format: "{c}"

# Some additional info about LDAP connectors:
#
# Unlike the CSV connector, the LDAP connector does not have custom specifications
Expand Down
80 changes: 80 additions & 0 deletions examples/config files - basic/5 connector-okta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,83 @@ all_users_filter: 'user.status == "ACTIVE"'
# the valid values are: enterpriseID, federatedID
# If not specified, the default identity type from the main config file is used.
# user_identity_type: federatedID

# (optional) string_encoding (default value given below)
# string_encoding specifies the Unicode string encoding used by the directory.
# All values retrieved from the directory are converted to Unicode before being
# sent to or compared with values on the Adobe side, to avoid encoding issues.
# The value must be a Python codec name or alias, such as 'latin1' or 'big5'.
# See https://docs.python.org/2/library/codecs.html#standard-encodings for details.
#string_encoding: utf8

# (optional) user_identity_type_format (no default)
# user_identity_type_format specifies how to construct a user's desired identity
# type on the Adobe side by combining constant strings with attribute values.
# Any names in curly braces are take as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# There is no default value for this setting, because most directories don't contain
# users with different identity types (so setting the default identity type suffices).
# If your directory contains users of different identity types, you should define
# this field to look at the value of an appropriate attribute in your okta user profile.
# For example, if your Okta user profile attribute "idType" had one of the values
# adobe, enterprise, or federated in it for each user, you could use:
#user_identity_type_format: "{idType}ID"

# (optional) user_email_format (default value given below)
# user_email_format specifies how to construct a user's email address by
# combining constant strings with the values of specific Okta profile attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value is from "email" field in Okta user profile.
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
user_email_format: "{email}"

# (optional) user_domain_format (no default value)
# user_domain_format is analogous to user_email_format in syntax, but it
# is used to discover the domain for a given user. If not specified, the
# domain is taken from the domain part of the user's email address.
#user_domain_format: "{domain}"

# (optional) user_username_format (no default value)
# user_username_format specifies how to construct a user's username on the
# Adobe side by combining constant strings with attribute values.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# This setting should only be used when you are using federatedID and your
# federation configuration specifies username-based login. In all other cases,
# make sure this is not set or returns an empty value, and the user's username
# will be taken from the user's email.
# This example supposes that the department and user_id are concatenated to
# produce a unique username for each user.
#user_username_format: "{department}_{user_id}"

# (optional) user_given_name_format (default value given below)
# user_given_name_format specifies how to construct a user's given name by
# combining constant strings with the values of specific Okta profile attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value is from "firstName" field in Okta user profile..
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
#user_given_name_format: "{firstName}"

# (optional) user_surname_format (default value given below)
# user_surname_format specifies how to construct a user's surname by
# combining constant strings with the values of specific Okta profile attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value is from "lastName" field in Okta user profile.
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
#user_surname_format: "{lastName}"

# (optional) user_country_code_format (default value given below)
# user_country_code_format specifies how to construct a user's country code by
# combining constant strings with the values of specific Okta profile attributes.
# Any names in curly braces are taken as attribute names, and everything including
# the braces will be replaced on a per-user basis with the values of the attributes.
# The default value is from "countryCode" field in Okta user profile.
# NOTE: for this and every format setting, the constant strings must be in
# the encoding specified by the string_encoding setting, above.
#user_country_code_format: "{countryCode}"
23 changes: 19 additions & 4 deletions user_sync/connector/directory_ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ def __init__(self, caller_options):
builder.set_string_value('user_email_format', six.text_type('{mail}'))
builder.set_string_value('user_username_format', None)
builder.set_string_value('user_domain_format', None)
builder.set_string_value('user_given_name_format', six.text_type('{givenName}'))
builder.set_string_value('user_surname_format', six.text_type('{sn}'))
builder.set_string_value('user_country_code_format', six.text_type('{c}'))
builder.set_string_value('user_identity_type', None)
builder.set_int_value('search_page_size', 200)
builder.set_string_value('logger_name', LDAPDirectoryConnector.name)
Expand All @@ -93,6 +96,9 @@ def __init__(self, caller_options):
self.user_email_formatter = LDAPValueFormatter(options['user_email_format'])
self.user_username_formatter = LDAPValueFormatter(options['user_username_format'])
self.user_domain_formatter = LDAPValueFormatter(options['user_domain_format'])
self.user_given_name_formatter = LDAPValueFormatter(options['user_given_name_format'])
self.user_surname_formatter = LDAPValueFormatter(options['user_surname_format'])
self.user_country_code_formatter = LDAPValueFormatter(options['user_country_code_format'])

password = caller_config.get_credential('password', options['username'])
# this check must come after we get the password value
Expand Down Expand Up @@ -195,7 +201,10 @@ def iter_users(self, users_filter, extended_attributes):
options = self.options
base_dn = six.text_type(options['base_dn'])

user_attribute_names = [six.text_type('givenName'), six.text_type('sn'), six.text_type('c')]
user_attribute_names = []
user_attribute_names.extend(self.user_given_name_formatter.get_attribute_names())
user_attribute_names.extend(self.user_surname_formatter.get_attribute_names())
user_attribute_names.extend(self.user_country_code_formatter.get_attribute_names())
user_attribute_names.extend(self.user_identity_type_formatter.get_attribute_names())
user_attribute_names.extend(self.user_email_formatter.get_attribute_names())
user_attribute_names.extend(self.user_username_formatter.get_attribute_names())
Expand Down Expand Up @@ -261,18 +270,24 @@ def iter_users(self, users_filter, extended_attributes):
elif last_attribute_name:
self.logger.warning('No domain attribute (%s) for user with dn: %s', last_attribute_name, dn)

given_name_value = LDAPValueFormatter.get_attribute_value(record, six.text_type('givenName'))
given_name_value, last_attribute_name = self.user_given_name_formatter.generate_value(record)
source_attributes['givenName'] = given_name_value
if given_name_value is not None:
user['firstname'] = given_name_value
sn_value = LDAPValueFormatter.get_attribute_value(record, six.text_type('sn'))
elif last_attribute_name:
self.logger.warning('No given name attribute (%s) for user with dn: %s', last_attribute_name, dn)
sn_value, last_attribute_name = self.user_surname_formatter.generate_value(record)
source_attributes['sn'] = sn_value
if sn_value is not None:
user['lastname'] = sn_value
c_value = LDAPValueFormatter.get_attribute_value(record, six.text_type('c'))
elif last_attribute_name:
self.logger.warning('No surname attribute (%s) for user with dn: %s', last_attribute_name, dn)
c_value, last_attribute_name = self.user_country_code_formatter.generate_value(record)
source_attributes['c'] = c_value
if c_value is not None:
user['country'] = c_value.upper()
elif last_attribute_name:
self.logger.warning('No country code attribute (%s) for user with dn: %s', last_attribute_name, dn)

if extended_attributes is not None:
for extended_attribute in extended_attributes:
Expand Down
Loading