def add_security_contact_person(self, email): if email == self.security_contact_email: return NSMAP = { None: NAMESPACES['md'], 'remd': NAMESPACES['remd'] } contact_person_tag = addns('ContactPerson', NAMESPACES['md']) contact_type_attr = addns('contactType', NAMESPACES['remd']) people = self.security_contact_people if len(people): contact_person_el = people[0] else: contact_person_el = etree.Element(contact_person_tag, **{ contact_type_attr: 'http://refeds.org/metadata/contactType/security', 'contactType': 'other', 'nsmap': NSMAP }) email_tag = addns('EmailAddress', NAMESPACES['md']) email_el = contact_person_el.find(email_tag) if email_el is None: email_el = etree.SubElement(contact_person_el, email_tag) email_el.text = 'mailto:{!s}'.format(email) self.etree.append(contact_person_el) return contact_person_el
def add_contact(self, contact, type): contacts = self.get_contact_people(type) if len(contacts): contact_el = contacts[0] else: contact_el = self.add_contact_person(type) if contact.name: name_tag = addns('SurName', NAMESPACES['md']) name_el = contact_el.find(name_tag) if name_el is None: name_el = etree.Element(name_tag) name_el.text = contact.name contact_el.insert(0, name_el) if contact.given_name: gname_tag = addns('GivenName', NAMESPACES['md']) gname_el = contact_el.find(gname_tag) if gname_el is None: gname_el = etree.Element(gname_tag) gname_el.text = contact.given_name contact_el.insert(0, gname_el) if contact.email: email_tag = addns('EmailAddress', NAMESPACES['md']) email_el = contact_el.find(email_tag) if email_el is None: email_el = etree.Element(email_tag) email_el.text = 'mailto:{!s}'.format(contact.email) contact_el.append(email_el) if contact.phone: phone_tag = addns('TelephoneNumber', NAMESPACES['md']) phone_el = contact_el.find(phone_tag) if phone_el is None: phone_el = etree.Element(phone_tag) phone_el.text = contact.phone contact_el.append(phone_el) return contact_el
def geolocationhint(self): path = [addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('GeolocationHint', MDUI_NAMESPACE)] result = self.etree.find('/'.join(path)) if result is not None: latitude, longitude = result.text.replace('geo:', '').split(',') return {'latitude': latitude, 'longitude': longitude} else: return None
def add_mdui_info_piece(self, tag, data, lang): mdui_piece_el = self.get_mdui_info_piece(tag, lang) if mdui_piece_el is not None: mdui_piece_el.text = data return uiinfo_el = self.get_or_create_uiinfo_el() xml_tag = addns(tag, NAMESPACES['mdui']) lang_attr = addns('lang', NAMESPACES['xml']) element = etree.SubElement(uiinfo_el, xml_tag, **{lang_attr: lang}) element.text = data return element
def role_descriptor(self): path = [addns('IDPSSODescriptor'), ] find_xml = self.etree.find('/'.join(path)) path2 = [addns('SPSSODescriptor'), ] find_xml2 = self.etree.find('/'.join(path2)) if find_xml is not None and find_xml2 is not None: res = 'Both' elif find_xml is None: res = 'SP' else: res = 'IDP' return res
def get_or_create_descriptor_extensions_el(self): if self.role_descriptor == 'SP': descriptor_tag = addns('SPSSODescriptor') else: descriptor_tag = addns('IDPSSODescriptor') descriptor_el = self.etree.find('.//{!s}'.format(descriptor_tag)) extensions_tag = addns('Extensions', NAMESPACES['md']) extensions_el = descriptor_el.find(extensions_tag) if extensions_el is None: extensions_el = etree.Element(extensions_tag) descriptor_el.insert(0, extensions_el) return extensions_el
def display_name(self): languages = {} path = [addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('DisplayName', MDUI_NAMESPACE)] for dn_node in self.etree.findall('/'.join(path)): lang = getlang(dn_node) if lang is None: continue # the lang attribute is required languages[lang] = dn_node.text return languages
def geolocationhint(self): path = [ addns("SPSSODescriptor"), addns("Extensions"), addns("UIInfo", MDUI_NAMESPACE), addns("GeolocationHint", MDUI_NAMESPACE), ] result = self.etree.find("/".join(path)) if result is not None: latitude, longitude = result.text.replace("geo:", "").split(",") return {"latitude": latitude, "longitude": longitude} else: return None
def attributes(self): attrs = [] path = [addns('Extensions'), addns('EntityAttributes', MDATTR_NAMESPACE), addns('Attribute', SAML_NAMESPACE)] find_xml = self.etree.findall('/'.join(path)) for node_attr in find_xml: if node_attr is not None: element = {} for items in node_attr.items(): element[items[0]] = items[1] element['Value'] = node_attr.getchildren()[0].text attrs.append(element) return attrs
def geolocationhint(self): path = [ addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('GeolocationHint', MDUI_NAMESPACE) ] result = self.etree.find('/'.join(path)) if result is not None: latitude, longitude = result.text.replace('geo:', '').split(',') return {'latitude': latitude, 'longitude': longitude} else: return None
def add_mdui_info_piece(self, tag, data, lang): mdui_piece_el = self.get_mdui_info_piece(tag, lang) if mdui_piece_el is not None: mdui_piece_el.text = data return uiinfo_el = self.get_or_create_uiinfo_el() xml_tag = addns(tag, NAMESPACES['mdui']) lang_attr = addns('lang', NAMESPACES['xml']) element = etree.SubElement(uiinfo_el, xml_tag, **{ lang_attr: lang }) element.text = data return element
def display_name(self): languages = '' if self.role_descriptor == 'SP': path = [ addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('DisplayName', MDUI_NAMESPACE) ] else: path = [ addns('IDPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('DisplayName', MDUI_NAMESPACE) ] displays = self.etree.findall('/'.join(path)) for dn_node in displays: lang = getlang(dn_node) if lang is None: continue # the lang attribute is required if lang == 'en': languages = dn_node.text if languages == '' and len(displays) > 0: languages = displays[0].text return languages
def _has_categories_el(self, attr_name): extensions_tag = addns('Extensions', NAMESPACES['md']) extensions_el = self.etree.find(extensions_tag) if extensions_el is None: return False entity_attrs = addns('EntityAttributes', NAMESPACES['mdattr']) entity_attrs_el = extensions_el.find(entity_attrs) if entity_attrs_el is None: return False path = 'saml:Attribute[@Name="{!s}"]'.format(attr_name) categories_attr_el = entity_attrs_el.xpath(path, namespaces=NAMESPACES) if not categories_attr_el: return False return True
def collect_certificates_for_role(role): key_descr_path = [addns(role), addns("KeyDescriptor")] for key_descriptor in self.etree.findall("/".join(key_descr_path)): cert_path = [ addns("KeyInfo", XMLDSIG_NAMESPACE), addns("X509Data", XMLDSIG_NAMESPACE), addns("X509Certificate", XMLDSIG_NAMESPACE), ] for cert in key_descriptor.findall("/".join(cert_path)): if "use" in key_descriptor.attrib: result.append({"use": key_descriptor.attrib["use"], "text": cert.text}) else: result.append({"use": "signing and encryption", "text": cert.text})
def collect_certificates_for_role(role): key_descr_path = [addns(role), addns('KeyDescriptor')] for key_descriptor in self.etree.findall('/'.join(key_descr_path)): cert_path = [addns('KeyInfo', XMLDSIG_NAMESPACE), addns('X509Data', XMLDSIG_NAMESPACE), addns('X509Certificate', XMLDSIG_NAMESPACE)] for cert in key_descriptor.findall('/'.join(cert_path)): if 'use' in key_descriptor.attrib: result.append({'use': key_descriptor.attrib['use'], 'text': cert.text}) else: result.append({'use': 'signing and encryption', 'text': cert.text})
def get_or_create_entity_extensions_el(self): extensions_tag = addns('Extensions', NAMESPACES['md']) extensions_el = self.etree.find(extensions_tag) if extensions_el is None: extensions_el = etree.Element(extensions_tag) self.etree.insert(0, extensions_el) return extensions_el
def role_descriptor(self): path = [ addns('IDPSSODescriptor'), ] find_xml = self.etree.find('/'.join(path)) path2 = [ addns('SPSSODescriptor'), ] find_xml2 = self.etree.find('/'.join(path2)) if find_xml is not None and find_xml2 is not None: res = 'Both' elif find_xml is None: res = 'SP' else: res = 'IDP' return res
def get_or_create_entity_attrs_el(self): extensions_el = self.get_or_create_entity_extensions_el() entity_attrs = addns('EntityAttributes', NAMESPACES['mdattr']) entity_attrs_el = extensions_el.find(entity_attrs) if entity_attrs_el is None: entity_attrs_el = etree.SubElement(extensions_el, entity_attrs) return entity_attrs_el
def display_name(self): languages = {} path = [ addns("SPSSODescriptor"), addns("Extensions"), addns("UIInfo", MDUI_NAMESPACE), addns("DisplayName", MDUI_NAMESPACE), ] for dn_node in self.etree.findall("/".join(path)): lang = getlang(dn_node) if lang is None: continue # the lang attribute is required languages[lang] = dn_node.text return languages
def has_uiinfo_el(self): extensions_el = self.get_or_create_descriptor_extensions_el() uiinfo_tag = addns('UIInfo', NAMESPACES['mdui']) uiinfo_el = extensions_el.find(uiinfo_tag) if uiinfo_el is None: return False return True
def get_or_create_uiinfo_el(self): extensions_el = self.get_or_create_descriptor_extensions_el() uiinfo_tag = addns('UIInfo', NAMESPACES['mdui']) uiinfo_el = extensions_el.find(uiinfo_tag) if uiinfo_el is None: uiinfo_el = etree.SubElement(extensions_el, uiinfo_tag) return uiinfo_el
def add_sirtfi_id_assurance(self): certification_el = self.get_or_create_assurance_certification_el() for child in certification_el.getchildren(): if child.text == CERTIFICATIONS['SIRTFI']: break else: sirtfi = etree.SubElement( certification_el, addns('AttributeValue', NAMESPACES['saml'])) sirtfi.text = CERTIFICATIONS['SIRTFI']
def organization(self): languages = {} for org_node in self.etree.findall(addns("Organization")): for attr in ("name", "displayName", "URL"): node_name = "Organization" + attr[0].upper() + attr[1:] for node in org_node.findall(addns(node_name)): lang = getlang(node) if lang is None: continue # the lang attribute is required lang_dict = languages.setdefault(lang, {}) lang_dict[attr] = node.text result = [] for lang, data in languages.items(): data["lang"] = lang result.append(data) return result
def add_sirtfi_id_assurance(self): certification_el = self.get_or_create_assurance_certification_el() for child in certification_el.getchildren(): if child.text == CERTIFICATIONS['SIRTFI']: break else: sirtfi = etree.SubElement(certification_el, addns('AttributeValue', NAMESPACES['saml'])) sirtfi.text = CERTIFICATIONS['SIRTFI']
def add_mdui_logo(self, data, lang, height, width): tag = 'Logo' logo_el = self.get_mdui_info_piece(tag, lang) if logo_el is not None: logo_el.text = data logo_el.attrib['height'] = height logo_el.attrib['width'] = width return uiinfo_el = self.get_or_create_uiinfo_el() xml_tag = addns(tag, NAMESPACES['mdui']) lang_attr = addns('lang', NAMESPACES['xml']) element = etree.SubElement(uiinfo_el, xml_tag, **{ lang_attr: lang, 'height': height, 'width': width, }) element.text = data return element
def attributes(self): attrs = [] path = [ addns('Extensions'), addns('EntityAttributes', MDATTR_NAMESPACE), addns('Attribute', SAML_NAMESPACE) ] find_xml = self.etree.findall('/'.join(path)) for node_attr in find_xml: if node_attr is not None: element = {} for items in node_attr.items(): element[items[0]] = items[1] children = node_attr.getchildren() if len(children): element['Value'] = children[0].text attrs.append(element) return attrs
def security_contact_email(self): people = self.security_contact_people email_tag = addns('EmailAddress', NAMESPACES['md']) for person in people: email_el = person.find(email_tag) if email_el is not None: email = email_el.text if email.startswith('mailto:'): email = email[7:] return email
def organization(self): languages = {} for org_node in self.etree.findall(addns('Organization')): for attr in (('name', 'Name'), ('displayName', 'DisplayName'), ('URL', 'URL')): node_name = 'Organization' + attr[1] for node in org_node.findall(addns(node_name)): lang = getlang(node) if lang is None: continue # the lang attribute is required lang_dict = languages.setdefault(lang, {}) lang_dict[attr[0]] = node.text result = [] for lang, data in languages.items(): data['lang'] = lang result.append(data) return result
def add_mdui_logo(self, data, lang, height, width): tag = 'Logo' logo_el = self.get_mdui_info_piece(tag, lang) if logo_el is not None: logo_el.text = data logo_el.attrib['height'] = height logo_el.attrib['width'] = width return uiinfo_el = self.get_or_create_uiinfo_el() xml_tag = addns(tag, NAMESPACES['mdui']) lang_attr = addns('lang', NAMESPACES['xml']) element = etree.SubElement( uiinfo_el, xml_tag, **{ lang_attr: lang, 'height': height, 'width': width, }) element.text = data return element
def collect_certificates_for_role(role): key_descr_path = [addns(role), addns('KeyDescriptor')] for key_descriptor in self.etree.findall('/'.join(key_descr_path)): cert_path = [ addns('KeyInfo', XMLDSIG_NAMESPACE), addns('X509Data', XMLDSIG_NAMESPACE), addns('X509Certificate', XMLDSIG_NAMESPACE) ] for cert in key_descriptor.findall('/'.join(cert_path)): if 'use' in key_descriptor.attrib: result.append({ 'use': key_descriptor.attrib['use'], 'text': cert.text }) else: result.append({ 'use': 'signing and encryption', 'text': cert.text })
def add_contact_person(self, type): NSMAP = { None: NAMESPACES['md'], } contact_person_tag = addns('ContactPerson', NAMESPACES['md']) contact_person_el = etree.Element(contact_person_tag, **{ 'contactType': type, 'nsmap': NSMAP }) self.etree.append(contact_person_el) return contact_person_el
def add_contact_person(self, type): NSMAP = { None: NAMESPACES['md'], } contact_person_tag = addns('ContactPerson', NAMESPACES['md']) contact_person_el = etree.Element( contact_person_tag, **{ 'contactType': type, 'nsmap': NSMAP }) self.etree.append(contact_person_el) return contact_person_el
def logos(self): languages = {} path = [addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('Logo', MDUI_NAMESPACE)] for logo_node in self.etree.findall('/'.join(path)): lang = getlang(logo_node) if lang is None: continue # the lang attribute is required lang_dict = languages.setdefault(lang, {}) lang_dict['width'] = logo_node.attrib.get('width', '') lang_dict['height'] = logo_node.attrib.get('height', '') lang_dict['location'] = logo_node.text result = [] for lang, data in languages.items(): data['lang'] = lang result.append(data) return result
def contacts(self): result = [] for contact_node in self.etree.findall(addns('ContactPerson')): contact = {} if 'contactType' in contact_node.attrib: contact['type'] = contact_node.attrib['contactType'] for child in contact_node: contact[delns(child.tag)] = child.text result.append(contact) return result
def _add_categories(self, el, prev, possible, categories): for category in categories: if category not in prev: cat = etree.SubElement(el, addns('AttributeValue', NAMESPACES['saml'])) cat.text = category for category in possible.values(): if category not in categories: path = 'saml:AttributeValue[. = "{!s}"]'.format(category) attr_values = el.xpath(path, namespaces=NAMESPACES) for val in attr_values: val.getparent().remove(val) self._remove_childless_ancestors(el)
def contacts(self): result = [] for contact_node in self.etree.findall(addns("ContactPerson")): contact = {} if "contactType" in contact_node.attrib: contact["type"] = contact_node.attrib["contactType"] for child in contact_node: contact[delns(child.tag)] = child.text result.append(contact) return result
def _get_or_create_categories_el(self, attr_name): entity_attrs_el = self.get_or_create_entity_attrs_el() path = 'saml:Attribute[@Name="{!s}"]'.format(attr_name) categories_attr_els = entity_attrs_el.xpath(path, namespaces=NAMESPACES) if not categories_attr_els: NSMAP = {None: NAMESPACES['saml']} categories_attr_el = etree.SubElement(entity_attrs_el, addns('Attribute', NAMESPACES['saml']), NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri", Name=attr_name, nsmap=NSMAP) else: categories_attr_el = categories_attr_els[0] return categories_attr_el
def _add_categories(self, el, prev, possible, categories): for category in categories: if category not in prev: cat = etree.SubElement( el, addns('AttributeValue', NAMESPACES['saml'])) cat.text = category for category in possible.values(): if category not in categories: path = 'saml:AttributeValue[. = "{!s}"]'.format(category) attr_values = el.xpath(path, namespaces=NAMESPACES) for val in attr_values: val.getparent().remove(val) self._remove_childless_ancestors(el)
def add_security_contact_person(self, email): if email == self.security_contact_email: return NSMAP = {None: NAMESPACES['md'], 'remd': NAMESPACES['remd']} contact_person_tag = addns('ContactPerson', NAMESPACES['md']) contact_type_attr = addns('contactType', NAMESPACES['remd']) people = self.security_contact_people if len(people): contact_person_el = people[0] else: contact_person_el = etree.Element( contact_person_tag, **{ contact_type_attr: 'http://refeds.org/metadata/contactType/security', 'contactType': 'other', 'nsmap': NSMAP }) email_tag = addns('EmailAddress', NAMESPACES['md']) email_el = contact_person_el.find(email_tag) if email_el is None: email_el = etree.SubElement(contact_person_el, email_tag) email_el.text = 'mailto:{!s}'.format(email) self.etree.append(contact_person_el) return contact_person_el
def logos(self): languages = {} path = [ addns("SPSSODescriptor"), addns("Extensions"), addns("UIInfo", MDUI_NAMESPACE), addns("Logo", MDUI_NAMESPACE), ] for logo_node in self.etree.findall("/".join(path)): lang = getlang(logo_node) if lang is None: continue # the lang attribute is required lang_dict = languages.setdefault(lang, {}) lang_dict["width"] = logo_node.attrib.get("width", "") lang_dict["height"] = logo_node.attrib.get("height", "") lang_dict["location"] = logo_node.text result = [] for lang, data in languages.items(): data["lang"] = lang result.append(data) return result
def endpoints(self): result = [] def populate_endpoint(node, endpoint): for attr in ("Binding", "Location"): if attr in node.attrib: endpoint[attr] = node.attrib[attr] for role, endpoints in { "IDPSSODescriptor": [ "Artifact Resolution Service", "Assertion ID Request Service", "Manage Name ID Service", "Name ID Mapping Service", "Single Logout Service", "Single Sign On Service", ], "SPSSODescriptor": [ "Artifact Resolution Service", "Assertion Consumer Service", "Manage Name ID Service", "Single Logout Service", "Request Initiator", "Discovery Response", ], }.items(): for endpoint in endpoints: endpoint_id = endpoint.replace(" ", "") # remove spaces path = [addns(role), addns(endpoint_id)] for endpoint_node in self.etree.findall("/".join(path)): endpoint = {"Type": endpoint} populate_endpoint(endpoint_node, endpoint) result.append(endpoint) return result
def endpoints(self): result = [] def populate_endpoint(node, endpoint): for attr in ('Binding', 'Location'): if attr in node.attrib: endpoint[attr] = node.attrib[attr] for role, endpoints in { 'IDPSSODescriptor': [ 'Artifact Resolution Service', 'Assertion ID Request Service', 'Manage Name ID Service', 'Name ID Mapping Service', 'Single Logout Service', 'Single Sign On Service', ], 'SPSSODescriptor': [ 'Artifact Resolution Service', 'Assertion Consumer Service', 'Manage Name ID Service', 'Single Logout Service', 'Request Initiator', 'Discovery Response', ], }.items(): for endpoint in endpoints: endpoint_id = endpoint.replace(' ', '') # remove spaces path = [addns(role), addns(endpoint_id)] for endpoint_node in self.etree.findall('/'.join(path)): endpoint_aux = {'Type': endpoint} populate_endpoint(endpoint_node, endpoint_aux) result.append(endpoint_aux) return result
def logos(self): languages = {} path = [ addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('Logo', MDUI_NAMESPACE) ] for logo_node in self.etree.findall('/'.join(path)): lang = getlang(logo_node) if lang is None: continue # the lang attribute is required lang_dict = languages.setdefault(lang, {}) lang_dict['width'] = logo_node.attrib.get('width', '') lang_dict['height'] = logo_node.attrib.get('height', '') lang_dict['location'] = logo_node.text result = [] for lang, data in languages.items(): data['lang'] = lang result.append(data) return result
def _get_or_create_categories_el(self, attr_name): entity_attrs_el = self.get_or_create_entity_attrs_el() path = 'saml:Attribute[@Name="{!s}"]'.format(attr_name) categories_attr_els = entity_attrs_el.xpath(path, namespaces=NAMESPACES) if not categories_attr_els: NSMAP = {None: NAMESPACES['saml']} categories_attr_el = etree.SubElement( entity_attrs_el, addns('Attribute', NAMESPACES['saml']), NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri", Name=attr_name, nsmap=NSMAP) else: categories_attr_el = categories_attr_els[0] return categories_attr_el
def description(self): desc = '' if self.role_descriptor == 'SP': path = [ addns('SPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('Description', MDUI_NAMESPACE) ] else: path = [ addns('IDPSSODescriptor'), addns('Extensions'), addns('UIInfo', MDUI_NAMESPACE), addns('Description', MDUI_NAMESPACE) ] find_xml = self.etree.findall('/'.join(path)) for item in find_xml: if item is not None: if 'en' in item.values(): desc = item.text if desc == '' and len(find_xml) > 0: desc = find_xml[0].text return desc
def get_contact_data(self, tag, type): for contact in self.get_contact_people(type): element = contact.find(addns(tag)) if element is not None: return element.text