authentik.sources.saml.processors.metadata
SAML Service Provider Metadata Processor
1"""SAML Service Provider Metadata Processor""" 2 3from django.http import HttpRequest 4from lxml.etree import Element, SubElement, tostring # nosec 5 6from authentik.common.saml.constants import ( 7 NS_MAP, 8 NS_SAML_METADATA, 9 NS_SIGNATURE, 10 SAML_BINDING_POST, 11) 12from authentik.providers.saml.utils.encoding import strip_pem_header 13from authentik.sources.saml.models import SAMLSource 14 15 16class MetadataProcessor: 17 """SAML Service Provider Metadata Processor""" 18 19 source: SAMLSource 20 http_request: HttpRequest 21 22 def __init__(self, source: SAMLSource, request: HttpRequest): 23 self.source = source 24 self.http_request = request 25 26 # Using type unions doesn't work with cython types (which is what lxml is) 27 def get_signing_key_descriptor(self) -> Element | None: # noqa: UP007 28 """Get Signing KeyDescriptor, if enabled for the source""" 29 if self.source.signing_kp: 30 key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") 31 key_descriptor.attrib["use"] = "signing" 32 key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo") 33 x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data") 34 x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate") 35 x509_certificate.text = strip_pem_header( 36 self.source.signing_kp.certificate_data.replace("\r", "") 37 ).replace("\n", "") 38 return key_descriptor 39 return None 40 41 def get_encryption_key_descriptor(self) -> Element | None: # noqa: UP007 42 """Get Encryption KeyDescriptor, if enabled for the source""" 43 if self.source.encryption_kp: 44 key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") 45 key_descriptor.attrib["use"] = "encryption" 46 key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo") 47 x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data") 48 x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate") 49 x509_certificate.text = strip_pem_header( 50 self.source.encryption_kp.certificate_data.replace("\r", "") 51 ).replace("\n", "") 52 return key_descriptor 53 return None 54 55 def get_name_id_format(self) -> Element: 56 element = Element(f"{{{NS_SAML_METADATA}}}NameIDFormat") 57 element.text = self.source.name_id_policy 58 return element 59 60 def build_entity_descriptor(self) -> str: 61 """Build full EntityDescriptor""" 62 entity_descriptor = Element(f"{{{NS_SAML_METADATA}}}EntityDescriptor", nsmap=NS_MAP) 63 entity_descriptor.attrib["entityID"] = self.source.get_issuer(self.http_request) 64 65 sp_sso_descriptor = SubElement(entity_descriptor, f"{{{NS_SAML_METADATA}}}SPSSODescriptor") 66 sp_sso_descriptor.attrib["protocolSupportEnumeration"] = ( 67 "urn:oasis:names:tc:SAML:2.0:protocol" 68 ) 69 70 signing_descriptor = self.get_signing_key_descriptor() 71 if signing_descriptor is not None: 72 sp_sso_descriptor.append(signing_descriptor) 73 74 encryption_descriptor = self.get_encryption_key_descriptor() 75 if encryption_descriptor is not None: 76 sp_sso_descriptor.append(encryption_descriptor) 77 78 sp_sso_descriptor.append(self.get_name_id_format()) 79 80 assertion_consumer_service = SubElement( 81 sp_sso_descriptor, f"{{{NS_SAML_METADATA}}}AssertionConsumerService" 82 ) 83 assertion_consumer_service.attrib["isDefault"] = "true" 84 assertion_consumer_service.attrib["index"] = "0" 85 assertion_consumer_service.attrib["Binding"] = SAML_BINDING_POST 86 assertion_consumer_service.attrib["Location"] = self.source.build_full_url( 87 self.http_request 88 ) 89 90 return tostring(entity_descriptor).decode()
class
MetadataProcessor:
17class MetadataProcessor: 18 """SAML Service Provider Metadata Processor""" 19 20 source: SAMLSource 21 http_request: HttpRequest 22 23 def __init__(self, source: SAMLSource, request: HttpRequest): 24 self.source = source 25 self.http_request = request 26 27 # Using type unions doesn't work with cython types (which is what lxml is) 28 def get_signing_key_descriptor(self) -> Element | None: # noqa: UP007 29 """Get Signing KeyDescriptor, if enabled for the source""" 30 if self.source.signing_kp: 31 key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") 32 key_descriptor.attrib["use"] = "signing" 33 key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo") 34 x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data") 35 x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate") 36 x509_certificate.text = strip_pem_header( 37 self.source.signing_kp.certificate_data.replace("\r", "") 38 ).replace("\n", "") 39 return key_descriptor 40 return None 41 42 def get_encryption_key_descriptor(self) -> Element | None: # noqa: UP007 43 """Get Encryption KeyDescriptor, if enabled for the source""" 44 if self.source.encryption_kp: 45 key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") 46 key_descriptor.attrib["use"] = "encryption" 47 key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo") 48 x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data") 49 x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate") 50 x509_certificate.text = strip_pem_header( 51 self.source.encryption_kp.certificate_data.replace("\r", "") 52 ).replace("\n", "") 53 return key_descriptor 54 return None 55 56 def get_name_id_format(self) -> Element: 57 element = Element(f"{{{NS_SAML_METADATA}}}NameIDFormat") 58 element.text = self.source.name_id_policy 59 return element 60 61 def build_entity_descriptor(self) -> str: 62 """Build full EntityDescriptor""" 63 entity_descriptor = Element(f"{{{NS_SAML_METADATA}}}EntityDescriptor", nsmap=NS_MAP) 64 entity_descriptor.attrib["entityID"] = self.source.get_issuer(self.http_request) 65 66 sp_sso_descriptor = SubElement(entity_descriptor, f"{{{NS_SAML_METADATA}}}SPSSODescriptor") 67 sp_sso_descriptor.attrib["protocolSupportEnumeration"] = ( 68 "urn:oasis:names:tc:SAML:2.0:protocol" 69 ) 70 71 signing_descriptor = self.get_signing_key_descriptor() 72 if signing_descriptor is not None: 73 sp_sso_descriptor.append(signing_descriptor) 74 75 encryption_descriptor = self.get_encryption_key_descriptor() 76 if encryption_descriptor is not None: 77 sp_sso_descriptor.append(encryption_descriptor) 78 79 sp_sso_descriptor.append(self.get_name_id_format()) 80 81 assertion_consumer_service = SubElement( 82 sp_sso_descriptor, f"{{{NS_SAML_METADATA}}}AssertionConsumerService" 83 ) 84 assertion_consumer_service.attrib["isDefault"] = "true" 85 assertion_consumer_service.attrib["index"] = "0" 86 assertion_consumer_service.attrib["Binding"] = SAML_BINDING_POST 87 assertion_consumer_service.attrib["Location"] = self.source.build_full_url( 88 self.http_request 89 ) 90 91 return tostring(entity_descriptor).decode()
SAML Service Provider Metadata Processor
MetadataProcessor( source: authentik.sources.saml.models.SAMLSource, request: django.http.request.HttpRequest)
def
get_signing_key_descriptor(self) -> lxml.etree.Element | None:
28 def get_signing_key_descriptor(self) -> Element | None: # noqa: UP007 29 """Get Signing KeyDescriptor, if enabled for the source""" 30 if self.source.signing_kp: 31 key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") 32 key_descriptor.attrib["use"] = "signing" 33 key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo") 34 x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data") 35 x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate") 36 x509_certificate.text = strip_pem_header( 37 self.source.signing_kp.certificate_data.replace("\r", "") 38 ).replace("\n", "") 39 return key_descriptor 40 return None
Get Signing KeyDescriptor, if enabled for the source
def
get_encryption_key_descriptor(self) -> lxml.etree.Element | None:
42 def get_encryption_key_descriptor(self) -> Element | None: # noqa: UP007 43 """Get Encryption KeyDescriptor, if enabled for the source""" 44 if self.source.encryption_kp: 45 key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") 46 key_descriptor.attrib["use"] = "encryption" 47 key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo") 48 x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data") 49 x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate") 50 x509_certificate.text = strip_pem_header( 51 self.source.encryption_kp.certificate_data.replace("\r", "") 52 ).replace("\n", "") 53 return key_descriptor 54 return None
Get Encryption KeyDescriptor, if enabled for the source
def
build_entity_descriptor(self) -> str:
61 def build_entity_descriptor(self) -> str: 62 """Build full EntityDescriptor""" 63 entity_descriptor = Element(f"{{{NS_SAML_METADATA}}}EntityDescriptor", nsmap=NS_MAP) 64 entity_descriptor.attrib["entityID"] = self.source.get_issuer(self.http_request) 65 66 sp_sso_descriptor = SubElement(entity_descriptor, f"{{{NS_SAML_METADATA}}}SPSSODescriptor") 67 sp_sso_descriptor.attrib["protocolSupportEnumeration"] = ( 68 "urn:oasis:names:tc:SAML:2.0:protocol" 69 ) 70 71 signing_descriptor = self.get_signing_key_descriptor() 72 if signing_descriptor is not None: 73 sp_sso_descriptor.append(signing_descriptor) 74 75 encryption_descriptor = self.get_encryption_key_descriptor() 76 if encryption_descriptor is not None: 77 sp_sso_descriptor.append(encryption_descriptor) 78 79 sp_sso_descriptor.append(self.get_name_id_format()) 80 81 assertion_consumer_service = SubElement( 82 sp_sso_descriptor, f"{{{NS_SAML_METADATA}}}AssertionConsumerService" 83 ) 84 assertion_consumer_service.attrib["isDefault"] = "true" 85 assertion_consumer_service.attrib["index"] = "0" 86 assertion_consumer_service.attrib["Binding"] = SAML_BINDING_POST 87 assertion_consumer_service.attrib["Location"] = self.source.build_full_url( 88 self.http_request 89 ) 90 91 return tostring(entity_descriptor).decode()
Build full EntityDescriptor