Skip to content

Commit d62946c

Browse files
skorandac00kiemon5ter
authored andcommitted
Better consumption of attributes from returned record
Better consumption of the attributes from the returned record to take into account handling of attributes from LDAP that include attribute options. Also included new option to determine whether attributes resolved from LDAP should overwrite existing internal attributes, the default, or be merged.
1 parent a580681 commit d62946c

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

src/satosa/micro_services/ldap_attribute_store.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import ldap3
1313
from ldap3.core.exceptions import LDAPException
1414

15+
from collections import defaultdict
16+
1517
from satosa.exception import SATOSAError
1618
from satosa.logging_util import satosa_logging
1719
from satosa.micro_services.base import ResponseMicroService
@@ -46,6 +48,7 @@ class LdapAttributeStore(ResponseMicroService):
4648
"ldap_to_internal_map": None,
4749
"on_ldap_search_result_empty": None,
4850
"ordered_identifier_candidates": None,
51+
"overwrite_existing_attributes": True,
4952
"search_base": None,
5053
"query_return_attributes": None,
5154
"search_return_attributes": None,
@@ -333,20 +336,35 @@ def _populate_attributes(self, config, record):
333336
"""
334337
Use a record found in LDAP to populate attributes.
335338
"""
339+
340+
ldap_attributes = record.get("attributes", None)
341+
if not ldap_attributes:
342+
msg = "No attributes returned with LDAP record"
343+
satosa_logging(logger, logging.DEBUG, msg, None)
344+
return
345+
336346
ldap_to_internal_map = (
337347
config["ldap_to_internal_map"]
338348
if config["ldap_to_internal_map"]
339349
# Deprecated configuration. Will be removed in future.
340350
else config["search_return_attributes"]
341351
)
342352

343-
new_attr_values = {
344-
internal_attr: value
345-
for attr, internal_attr in ldap_to_internal_map.items()
346-
for value in [record["attributes"].get(attr)]
347-
if value
348-
}
349-
return new_attr_values
353+
attributes = defaultdict(list)
354+
355+
for attr, values in ldap_attributes.items():
356+
internal_attr = ldap_to_internal_map.get(attr, None)
357+
if not internal_attr and ';' in attr:
358+
internal_attr = ldap_to_internal_map.get(attr.split(';')[0],
359+
None)
360+
361+
if internal_attr and values:
362+
attributes[internal_attr].extend(values)
363+
msg = "Recording internal attribute {} with values {}"
364+
msg = msg.format(internal_attr, attributes[internal_attr])
365+
satosa_logging(logger, logging.DEBUG, msg, None)
366+
367+
return attributes
350368

351369
def _populate_input_for_name_id(self, config, record, data):
352370
"""
@@ -399,7 +417,7 @@ def process(self, context, data):
399417
data.subject_id,
400418
data.subject_type,
401419
issuer,
402-
data.attriutes,
420+
data.attributes,
403421
)
404422
]
405423
# If we have constructed a non empty value then add it as the next
@@ -506,8 +524,12 @@ def process(self, context, data):
506524

507525
# Populate attributes as configured.
508526
new_attrs = self._populate_attributes(config, record)
509-
msg = "Updating internal attributes with new values {}".format(new_attrs)
510-
satosa_logging(logger, logging.DEBUG, msg, None)
527+
528+
overwrite = config["overwrite_existing_attributes"]
529+
for attr, values in new_attrs.items():
530+
if not overwrite:
531+
values = list(set(data.attributes.get(attr, []) + values))
532+
data.attributes[attr] = values
511533

512534
# Populate input for NameID if configured. SATOSA core does the
513535
# hashing of input to create a persistent NameID.

0 commit comments

Comments
 (0)