Skip to content
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

new: add microservice to expose info about IdP from SAML metadata as attributes #448

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
21 changes: 21 additions & 0 deletions example/plugins/microservices/metadata_attributes.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module: satosa.micro_services.attribute_modifications.AddMetadataAttributes
name: AddMetadataAttributes
config:
attribute_mapping:
- name: shibmd_scopes
type: shibmd_scopes
- name: contact_person_data
type: contact_person_data
- name: assurance_certifications
type: assurance_certifications
- name: registration_info
type: registration_info
- name: registration_authority
type: registration_authority
- name: entity_categories
type: entity_categories
- name: supported_entity_categories
type: supported_entity_categories
- name: entity_attributes
type: entity_attributes

59 changes: 59 additions & 0 deletions src/satosa/micro_services/attribute_modifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

logger = logging.getLogger(__name__)


class AddStaticAttributes(ResponseMicroService):
"""
Add static attributes to the responses.
Expand All @@ -21,6 +22,64 @@ def process(self, context, data):
return super().process(context, data)


class AddMetadataAttributes(ResponseMicroService):
"""
Add metadata-derived attributes to the responses.
"""

def __init__(self, config, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attribute_mapping = config["attribute_mapping"]

def process(self, context, data):
data.attributes.update(self.get_attribute_values(context, data.auth_info.issuer, self.attribute_mapping))
return super().process(context, data)

def get_attribute_values(self, context, target_provider, attribute_mapping):
attribute_values = {}
mdstore = context.get_decoration(Context.KEY_METADATA_STORE)
if not mdstore:
return attribute_values # empty: nothing we can do without an mdstore
for am in attribute_mapping:
value = None
if am['type'] == "shibmd_scopes":
scopes = mdstore.shibmd_scopes(target_provider, "idpsso_descriptor")

# saml2.MDStore.shibmd_scopes returns compiled RE Pattern objects, but these are not serializable.
# Replace them back with the original pattern text.
# And wrap the resulting list in a dict, as mod_auth_openidc does not accept lists of JSON objects.
value = {"scopes":
[
{"regexp": scope['regexp'], "text": scope['text'].pattern if scope['regexp'] else scope['text']}
for scope in scopes
]}
elif am['type'] == "contact_person_data":
# Convert tuple to a list to make it serializable.
# And wrap it in a dict, as mod_auth_openidc does not accept lists of JSON objects.
value = {"contacts": list(mdstore.contact_person_data(target_provider))}
elif am['type'] == "assurance_certifications":
# Convert tuple to a list to make it serializable.
value = list(mdstore.assurance_certifications(target_provider))
elif am['type'] == "registration_info":
value = mdstore.registration_info(target_provider)
elif am['type'] == "registration_authority":
registration_info = mdstore.registration_info(target_provider)
if registration_info and 'registration_authority' in registration_info:
value = registration_info['registration_authority']
elif am['type'] == "entity_categories":
value = mdstore.entity_categories(target_provider)
elif am['type'] == "supported_entity_categories":
value = mdstore.supported_entity_categories(target_provider)
elif am['type'] == "entity_attributes":
value = mdstore.entity_attributes(target_provider)
else:
raise SATOSAError("Unknown SAML metadata attribute type")

if value:
attribute_values[am['name']] = value
return attribute_values


class FilterAttributeValues(ResponseMicroService):
"""
Filter attribute values, only preserving those matching the given regex.
Expand Down