From b492a8aeb489ae36e74fa037697a28d270d35a21 Mon Sep 17 00:00:00 2001 From: Cristiano Singulani Date: Thu, 13 Jun 2024 17:23:36 +0000 Subject: [PATCH] Finished authentication integration with saml2 (replacement of shibboleth) --- .gitignore | 2 + README.md | 61 +++- backend/.gitignore | 4 +- backend/Dockerfile | 5 +- backend/attribute-maps/__init__.py | 2 + backend/attribute-maps/adfs_v1x.py | 18 ++ backend/attribute-maps/adfs_v20.py | 49 ++++ backend/attribute-maps/basic.py | 340 +++++++++++++++++++++++ backend/attribute-maps/saml_uri.py | 316 +++++++++++++++++++++ backend/attribute-maps/shibboleth_uri.py | 197 +++++++++++++ backend/core/saml2.py | 40 +++ backend/core/shibboleth.py | 62 ----- backend/core/shibboleth_urls.py | 12 - backend/pzserver/settings.py | 178 +++++++++--- backend/pzserver/urls.py | 25 +- backend/requirements.txt | 2 + docker-compose-development.yml | 1 + env_template | 32 ++- nginx_development.conf | 5 + nginx_production.conf | 25 +- 20 files changed, 1209 insertions(+), 167 deletions(-) create mode 100644 backend/attribute-maps/__init__.py create mode 100644 backend/attribute-maps/adfs_v1x.py create mode 100644 backend/attribute-maps/adfs_v20.py create mode 100644 backend/attribute-maps/basic.py create mode 100644 backend/attribute-maps/saml_uri.py create mode 100644 backend/attribute-maps/shibboleth_uri.py create mode 100644 backend/core/saml2.py delete mode 100644 backend/core/shibboleth.py delete mode 100644 backend/core/shibboleth_urls.py diff --git a/.gitignore b/.gitignore index 0756aee..fab525f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ nginx.conf # Docker Compose docker-compose.yml .env.local + +saml2 \ No newline at end of file diff --git a/README.md b/README.md index f3c26d5..ed04459 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Turn on background environment (if you have the application already running on t docker-compose up -d ``` - Access in the browser: +Access in the browser: - Frontend: - Django Admin: - Django REST: @@ -233,6 +233,64 @@ run single test method docker-compose exec backend pytest core/test/test_product_file.py::ProductFileListCreateAPIViewTestCase::test_list_product_file ``` +## Enable authentication via LIneA Satosa (Github) + +### Keys and certificates + +Edit the `.env` to include the path to the certificates for signing and encrypting SAML assertions: +(It is possible to use the same certificate for both signing and encryption.) + +```bash +# Keys and certificates +SIG_KEY_PEM= +SIG_CERT_PEM= +ENCRYP_KEY_PEM= +ENCRYP_CERT_PEM= +``` + +If you do not have valid certificates (not recommended in production), generate a self-signed certificate using the command below: + +Create the `certificates` directory with the following command: + +```bash +mkdir -p saml2/certificates + +openssl genrsa -out pz.key 2048 +openssl req -new -key pz.key -out pz.csr +openssl x509 -req -days 365 -in pz.csr -signkey pz.key -out pz.crt + +cp pz.key pzkey.pem +cp pz.crt pzcert.pem +``` + +Next we must uncomment the volume that represents the saml2 directory in docker-compose.yml: + +```yml +- ./archive/log/backend:/archive/log +- ./archive/data:/archive/data +- ./saml2:/saml2 # uncomment if authentication with github is required +``` + +### IDP Metadata (Github) + +Edit the `.env` and tell where the metadata can be found: +(Contact the infrastructure team to find out more details about the metadata.) + +```bash +# IDP metadata +IDP_METADATA= +``` + +And finally, just uncomment the `AUTH_SHIB_URL` variable in the `.env`: + +```bash +# Saml2 / Satosa Auth +# URL to login using satosa +AUTH_SHIB_URL=${URI}/saml2/login/ +``` + +With everything configured and the services started, we must access the URL `${URI}/saml2/metadata/` and send the content (xml) to the infrastructure team to create a trust relationship between the application and satosa. + ## Setup Production Enviroment In the production environment **NO** it is necessary to clone the repository. @@ -320,3 +378,4 @@ Procedure to update the production environment or any other that uses built imag - Edit the `.env` file to add new variables or change them if necessary. - Pull the new images with the `docker-compose pull` command. - Restart services `docker-compose stop && docker-compose up -d`. + diff --git a/backend/.gitignore b/backend/.gitignore index feb11a4..78c1299 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -163,4 +163,6 @@ cython_debug/ # Django django_static/ -archive/ \ No newline at end of file +archive/ + +saml2/ \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile index 6c24b5c..53cd1cb 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -15,6 +15,9 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ build-essential \ libpcre3 \ libpcre3-dev \ + xmlsec1 \ + libssl-dev \ + libsasl2-dev \ && apt-get clean \ && apt-get autoclean \ && apt-get autoremove --purge -y \ @@ -48,4 +51,4 @@ COPY --chmod=0775 ./start.sh /start.sh # Switch to non-priviliged user and run app USER $USERNAME -ENTRYPOINT [ "/entrypoint.sh" ] \ No newline at end of file +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/backend/attribute-maps/__init__.py b/backend/attribute-maps/__init__.py new file mode 100644 index 0000000..d041d3f --- /dev/null +++ b/backend/attribute-maps/__init__.py @@ -0,0 +1,2 @@ +__author__ = 'rohe0002' +__all__ = ["adfs_v1x", "adfs_v20", "basic", "saml_uri", "shibboleth_uri"] diff --git a/backend/attribute-maps/adfs_v1x.py b/backend/attribute-maps/adfs_v1x.py new file mode 100644 index 0000000..0f8d01a --- /dev/null +++ b/backend/attribute-maps/adfs_v1x.py @@ -0,0 +1,18 @@ +CLAIMS = 'http://schemas.xmlsoap.org/claims/' + + +MAP = { + "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", + 'fro': { + CLAIMS+'commonname': 'commonName', + CLAIMS+'emailaddress': 'emailAddress', + CLAIMS+'group': 'group', + CLAIMS+'upn': 'upn', + }, + 'to': { + 'commonName': CLAIMS+'commonname', + 'emailAddress': CLAIMS+'emailaddress', + 'group': CLAIMS+'group', + 'upn': CLAIMS+'upn', + } +} diff --git a/backend/attribute-maps/adfs_v20.py b/backend/attribute-maps/adfs_v20.py new file mode 100644 index 0000000..94150d0 --- /dev/null +++ b/backend/attribute-maps/adfs_v20.py @@ -0,0 +1,49 @@ +CLAIMS = 'http://schemas.xmlsoap.org/claims/' +COM_WS_CLAIMS = 'http://schemas.xmlsoap.com/ws/2005/05/identity/claims/' +MS_CLAIMS = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/' +ORG_WS_CLAIMS = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/' + + +MAP = { + "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", + 'fro': { + CLAIMS+'commonname': 'commonName', + CLAIMS+'group': 'group', + COM_WS_CLAIMS+'denyonlysid': 'denyOnlySid', + MS_CLAIMS+'authenticationmethod': 'authenticationMethod', + MS_CLAIMS+'denyonlyprimarygroupsid': 'denyOnlyPrimaryGroupSid', + MS_CLAIMS+'denyonlyprimarysid': 'denyOnlyPrimarySid', + MS_CLAIMS+'groupsid': 'groupSid', + MS_CLAIMS+'primarygroupsid': 'primaryGroupSid', + MS_CLAIMS+'primarysid': 'primarySid', + MS_CLAIMS+'role': 'role', + MS_CLAIMS+'windowsaccountname': 'windowsAccountName', + ORG_WS_CLAIMS+'emailaddress': 'emailAddress', + ORG_WS_CLAIMS+'givenname': 'givenName', + ORG_WS_CLAIMS+'name': 'name', + ORG_WS_CLAIMS+'nameidentifier': 'nameId', + ORG_WS_CLAIMS+'privatepersonalidentifier': 'privatePersonalId', + ORG_WS_CLAIMS+'surname': 'surname', + ORG_WS_CLAIMS+'upn': 'upn', + }, + 'to': { + 'authenticationMethod': MS_CLAIMS+'authenticationmethod', + 'commonName': CLAIMS+'commonname', + 'denyOnlyPrimaryGroupSid': MS_CLAIMS+'denyonlyprimarygroupsid', + 'denyOnlyPrimarySid': MS_CLAIMS+'denyonlyprimarysid', + 'denyOnlySid': COM_WS_CLAIMS+'denyonlysid', + 'emailAddress': ORG_WS_CLAIMS+'emailaddress', + 'givenName': ORG_WS_CLAIMS+'givenname', + 'group': CLAIMS+'group', + 'groupSid': MS_CLAIMS+'groupsid', + 'name': ORG_WS_CLAIMS+'name', + 'nameId': ORG_WS_CLAIMS+'nameidentifier', + 'primaryGroupSid': MS_CLAIMS+'primarygroupsid', + 'primarySid': MS_CLAIMS+'primarysid', + 'privatePersonalId': ORG_WS_CLAIMS+'privatepersonalidentifier', + 'role': MS_CLAIMS+'role', + 'surname': ORG_WS_CLAIMS+'surname', + 'upn': ORG_WS_CLAIMS+'upn', + 'windowsAccountName': MS_CLAIMS+'windowsaccountname', + } +} diff --git a/backend/attribute-maps/basic.py b/backend/attribute-maps/basic.py new file mode 100644 index 0000000..c05b6e9 --- /dev/null +++ b/backend/attribute-maps/basic.py @@ -0,0 +1,340 @@ +DEF = 'urn:mace:dir:attribute-def:' + + +MAP = { + "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", + 'fro': { + DEF+'aRecord': 'aRecord', + DEF+'aliasedEntryName': 'aliasedEntryName', + DEF+'aliasedObjectName': 'aliasedObjectName', + DEF+'associatedDomain': 'associatedDomain', + DEF+'associatedName': 'associatedName', + DEF+'audio': 'audio', + DEF+'authorityRevocationList': 'authorityRevocationList', + DEF+'buildingName': 'buildingName', + DEF+'businessCategory': 'businessCategory', + DEF+'c': 'c', + DEF+'cACertificate': 'cACertificate', + DEF+'cNAMERecord': 'cNAMERecord', + DEF+'carLicense': 'carLicense', + DEF+'certificateRevocationList': 'certificateRevocationList', + DEF+'cn': 'cn', + DEF+'co': 'co', + DEF+'commonName': 'commonName', + DEF+'countryName': 'countryName', + DEF+'crossCertificatePair': 'crossCertificatePair', + DEF+'dITRedirect': 'dITRedirect', + DEF+'dSAQuality': 'dSAQuality', + DEF+'dc': 'dc', + DEF+'deltaRevocationList': 'deltaRevocationList', + DEF+'departmentNumber': 'departmentNumber', + DEF+'description': 'description', + DEF+'destinationIndicator': 'destinationIndicator', + DEF+'displayName': 'displayName', + DEF+'distinguishedName': 'distinguishedName', + DEF+'dmdName': 'dmdName', + DEF+'dnQualifier': 'dnQualifier', + DEF+'documentAuthor': 'documentAuthor', + DEF+'documentIdentifier': 'documentIdentifier', + DEF+'documentLocation': 'documentLocation', + DEF+'documentPublisher': 'documentPublisher', + DEF+'documentTitle': 'documentTitle', + DEF+'documentVersion': 'documentVersion', + DEF+'domainComponent': 'domainComponent', + DEF+'drink': 'drink', + DEF+'eduOrgHomePageURI': 'eduOrgHomePageURI', + DEF+'eduOrgIdentityAuthNPolicyURI': 'eduOrgIdentityAuthNPolicyURI', + DEF+'eduOrgLegalName': 'eduOrgLegalName', + DEF+'eduOrgSuperiorURI': 'eduOrgSuperiorURI', + DEF+'eduOrgWhitePagesURI': 'eduOrgWhitePagesURI', + DEF+'eduCourseOffering': 'eduCourseOffering', + DEF+'eduCourseMember': 'eduCourseMember', + DEF+'eduPersonAffiliation': 'eduPersonAffiliation', + DEF+'eduPersonEntitlement': 'eduPersonEntitlement', + DEF+'eduPersonNickname': 'eduPersonNickname', + DEF+'eduPersonOrgDN': 'eduPersonOrgDN', + DEF+'eduPersonOrgUnitDN': 'eduPersonOrgUnitDN', + DEF+'eduPersonPrimaryAffiliation': 'eduPersonPrimaryAffiliation', + DEF+'eduPersonPrimaryOrgUnitDN': 'eduPersonPrimaryOrgUnitDN', + DEF+'eduPersonPrincipalName': 'eduPersonPrincipalName', + DEF+'eduPersonPrincipalNamePrior': 'eduPersonPrincipalNamePrior', + DEF+'eduPersonScopedAffiliation': 'eduPersonScopedAffiliation', + DEF+'eduPersonTargetedID': 'eduPersonTargetedID', + DEF+'eduPersonAssurance': 'eduPersonAssurance', + DEF+'eduPersonUniqueId': 'eduPersonUniqueId', + DEF+'eduPersonOrcid': 'eduPersonOrcid', + DEF+'email': 'email', + DEF+'emailAddress': 'emailAddress', + DEF+'employeeNumber': 'employeeNumber', + DEF+'employeeType': 'employeeType', + DEF+'enhancedSearchGuide': 'enhancedSearchGuide', + DEF+'facsimileTelephoneNumber': 'facsimileTelephoneNumber', + DEF+'favouriteDrink': 'favouriteDrink', + DEF+'fax': 'fax', + DEF+'federationFeideSchemaVersion': 'federationFeideSchemaVersion', + DEF+'friendlyCountryName': 'friendlyCountryName', + DEF+'generationQualifier': 'generationQualifier', + DEF+'givenName': 'givenName', + DEF+'gn': 'gn', + DEF+'homePhone': 'homePhone', + DEF+'homePostalAddress': 'homePostalAddress', + DEF+'homeTelephoneNumber': 'homeTelephoneNumber', + DEF+'host': 'host', + DEF+'houseIdentifier': 'houseIdentifier', + DEF+'info': 'info', + DEF+'initials': 'initials', + DEF+'internationaliSDNNumber': 'internationaliSDNNumber', + DEF+'janetMailbox': 'janetMailbox', + DEF+'jpegPhoto': 'jpegPhoto', + DEF+'knowledgeInformation': 'knowledgeInformation', + DEF+'l': 'l', + DEF+'labeledURI': 'labeledURI', + DEF+'localityName': 'localityName', + DEF+'mDRecord': 'mDRecord', + DEF+'mXRecord': 'mXRecord', + DEF+'mail': 'mail', + DEF+'mailPreferenceOption': 'mailPreferenceOption', + DEF+'manager': 'manager', + DEF+'member': 'member', + DEF+'mobile': 'mobile', + DEF+'mobileTelephoneNumber': 'mobileTelephoneNumber', + DEF+'nSRecord': 'nSRecord', + DEF+'name': 'name', + DEF+'norEduOrgAcronym': 'norEduOrgAcronym', + DEF+'norEduOrgNIN': 'norEduOrgNIN', + DEF+'norEduOrgSchemaVersion': 'norEduOrgSchemaVersion', + DEF+'norEduOrgUniqueIdentifier': 'norEduOrgUniqueIdentifier', + DEF+'norEduOrgUniqueNumber': 'norEduOrgUniqueNumber', + DEF+'norEduOrgUnitUniqueIdentifier': 'norEduOrgUnitUniqueIdentifier', + DEF+'norEduOrgUnitUniqueNumber': 'norEduOrgUnitUniqueNumber', + DEF+'norEduPersonBirthDate': 'norEduPersonBirthDate', + DEF+'norEduPersonLIN': 'norEduPersonLIN', + DEF+'norEduPersonNIN': 'norEduPersonNIN', + DEF+'o': 'o', + DEF+'objectClass': 'objectClass', + DEF+'organizationName': 'organizationName', + DEF+'organizationalStatus': 'organizationalStatus', + DEF+'organizationalUnitName': 'organizationalUnitName', + DEF+'otherMailbox': 'otherMailbox', + DEF+'ou': 'ou', + DEF+'owner': 'owner', + DEF+'pager': 'pager', + DEF+'pagerTelephoneNumber': 'pagerTelephoneNumber', + DEF+'personalSignature': 'personalSignature', + DEF+'personalTitle': 'personalTitle', + DEF+'photo': 'photo', + DEF+'physicalDeliveryOfficeName': 'physicalDeliveryOfficeName', + DEF+'pkcs9email': 'pkcs9email', + DEF+'postOfficeBox': 'postOfficeBox', + DEF+'postalAddress': 'postalAddress', + DEF+'postalCode': 'postalCode', + DEF+'preferredDeliveryMethod': 'preferredDeliveryMethod', + DEF+'preferredLanguage': 'preferredLanguage', + DEF+'presentationAddress': 'presentationAddress', + DEF+'protocolInformation': 'protocolInformation', + DEF+'pseudonym': 'pseudonym', + DEF+'registeredAddress': 'registeredAddress', + DEF+'rfc822Mailbox': 'rfc822Mailbox', + DEF+'roleOccupant': 'roleOccupant', + DEF+'roomNumber': 'roomNumber', + DEF+'sOARecord': 'sOARecord', + DEF+'searchGuide': 'searchGuide', + DEF+'secretary': 'secretary', + DEF+'seeAlso': 'seeAlso', + DEF+'serialNumber': 'serialNumber', + DEF+'singleLevelQuality': 'singleLevelQuality', + DEF+'sn': 'sn', + DEF+'st': 'st', + DEF+'stateOrProvinceName': 'stateOrProvinceName', + DEF+'street': 'street', + DEF+'streetAddress': 'streetAddress', + DEF+'subtreeMaximumQuality': 'subtreeMaximumQuality', + DEF+'subtreeMinimumQuality': 'subtreeMinimumQuality', + DEF+'supportedAlgorithms': 'supportedAlgorithms', + DEF+'supportedApplicationContext': 'supportedApplicationContext', + DEF+'surname': 'surname', + DEF+'telephoneNumber': 'telephoneNumber', + DEF+'teletexTerminalIdentifier': 'teletexTerminalIdentifier', + DEF+'telexNumber': 'telexNumber', + DEF+'textEncodedORAddress': 'textEncodedORAddress', + DEF+'title': 'title', + DEF+'uid': 'uid', + DEF+'uniqueIdentifier': 'uniqueIdentifier', + DEF+'uniqueMember': 'uniqueMember', + DEF+'userCertificate': 'userCertificate', + DEF+'userClass': 'userClass', + DEF+'userPKCS12': 'userPKCS12', + DEF+'userPassword': 'userPassword', + DEF+'userSMIMECertificate': 'userSMIMECertificate', + DEF+'userid': 'userid', + DEF+'x121Address': 'x121Address', + DEF+'x500UniqueIdentifier': 'x500UniqueIdentifier', + }, + 'to': { + 'aRecord': DEF+'aRecord', + 'aliasedEntryName': DEF+'aliasedEntryName', + 'aliasedObjectName': DEF+'aliasedObjectName', + 'associatedDomain': DEF+'associatedDomain', + 'associatedName': DEF+'associatedName', + 'audio': DEF+'audio', + 'authorityRevocationList': DEF+'authorityRevocationList', + 'buildingName': DEF+'buildingName', + 'businessCategory': DEF+'businessCategory', + 'c': DEF+'c', + 'cACertificate': DEF+'cACertificate', + 'cNAMERecord': DEF+'cNAMERecord', + 'carLicense': DEF+'carLicense', + 'certificateRevocationList': DEF+'certificateRevocationList', + 'cn': DEF+'cn', + 'co': DEF+'co', + 'commonName': DEF+'commonName', + 'countryName': DEF+'countryName', + 'crossCertificatePair': DEF+'crossCertificatePair', + 'dITRedirect': DEF+'dITRedirect', + 'dSAQuality': DEF+'dSAQuality', + 'dc': DEF+'dc', + 'deltaRevocationList': DEF+'deltaRevocationList', + 'departmentNumber': DEF+'departmentNumber', + 'description': DEF+'description', + 'destinationIndicator': DEF+'destinationIndicator', + 'displayName': DEF+'displayName', + 'distinguishedName': DEF+'distinguishedName', + 'dmdName': DEF+'dmdName', + 'dnQualifier': DEF+'dnQualifier', + 'documentAuthor': DEF+'documentAuthor', + 'documentIdentifier': DEF+'documentIdentifier', + 'documentLocation': DEF+'documentLocation', + 'documentPublisher': DEF+'documentPublisher', + 'documentTitle': DEF+'documentTitle', + 'documentVersion': DEF+'documentVersion', + 'domainComponent': DEF+'domainComponent', + 'drink': DEF+'drink', + 'eduOrgHomePageURI': DEF+'eduOrgHomePageURI', + 'eduOrgIdentityAuthNPolicyURI': DEF+'eduOrgIdentityAuthNPolicyURI', + 'eduOrgLegalName': DEF+'eduOrgLegalName', + 'eduOrgSuperiorURI': DEF+'eduOrgSuperiorURI', + 'eduOrgWhitePagesURI': DEF+'eduOrgWhitePagesURI', + 'eduCourseMember': DEF+'eduCourseMember', + 'eduCourseOffering': DEF+'eduCourseOffering', + 'eduPersonAffiliation': DEF+'eduPersonAffiliation', + 'eduPersonEntitlement': DEF+'eduPersonEntitlement', + 'eduPersonNickname': DEF+'eduPersonNickname', + 'eduPersonOrgDN': DEF+'eduPersonOrgDN', + 'eduPersonOrgUnitDN': DEF+'eduPersonOrgUnitDN', + 'eduPersonPrimaryAffiliation': DEF+'eduPersonPrimaryAffiliation', + 'eduPersonPrimaryOrgUnitDN': DEF+'eduPersonPrimaryOrgUnitDN', + 'eduPersonPrincipalName': DEF+'eduPersonPrincipalName', + 'eduPersonPrincipalNamePrior': DEF+'eduPersonPrincipalNamePrior', + 'eduPersonScopedAffiliation': DEF+'eduPersonScopedAffiliation', + 'eduPersonTargetedID': DEF+'eduPersonTargetedID', + 'eduPersonAssurance': DEF+'eduPersonAssurance', + 'eduPersonUniqueId': DEF+'eduPersonUniqueId', + 'eduPersonOrcid': DEF+'eduPersonOrcid', + 'email': DEF+'email', + 'emailAddress': DEF+'emailAddress', + 'employeeNumber': DEF+'employeeNumber', + 'employeeType': DEF+'employeeType', + 'enhancedSearchGuide': DEF+'enhancedSearchGuide', + 'facsimileTelephoneNumber': DEF+'facsimileTelephoneNumber', + 'favouriteDrink': DEF+'favouriteDrink', + 'fax': DEF+'fax', + 'federationFeideSchemaVersion': DEF+'federationFeideSchemaVersion', + 'friendlyCountryName': DEF+'friendlyCountryName', + 'generationQualifier': DEF+'generationQualifier', + 'givenName': DEF+'givenName', + 'gn': DEF+'gn', + 'homePhone': DEF+'homePhone', + 'homePostalAddress': DEF+'homePostalAddress', + 'homeTelephoneNumber': DEF+'homeTelephoneNumber', + 'host': DEF+'host', + 'houseIdentifier': DEF+'houseIdentifier', + 'info': DEF+'info', + 'initials': DEF+'initials', + 'internationaliSDNNumber': DEF+'internationaliSDNNumber', + 'janetMailbox': DEF+'janetMailbox', + 'jpegPhoto': DEF+'jpegPhoto', + 'knowledgeInformation': DEF+'knowledgeInformation', + 'l': DEF+'l', + 'labeledURI': DEF+'labeledURI', + 'localityName': DEF+'localityName', + 'mDRecord': DEF+'mDRecord', + 'mXRecord': DEF+'mXRecord', + 'mail': DEF+'mail', + 'mailPreferenceOption': DEF+'mailPreferenceOption', + 'manager': DEF+'manager', + 'member': DEF+'member', + 'mobile': DEF+'mobile', + 'mobileTelephoneNumber': DEF+'mobileTelephoneNumber', + 'nSRecord': DEF+'nSRecord', + 'name': DEF+'name', + 'norEduOrgAcronym': DEF+'norEduOrgAcronym', + 'norEduOrgNIN': DEF+'norEduOrgNIN', + 'norEduOrgSchemaVersion': DEF+'norEduOrgSchemaVersion', + 'norEduOrgUniqueIdentifier': DEF+'norEduOrgUniqueIdentifier', + 'norEduOrgUniqueNumber': DEF+'norEduOrgUniqueNumber', + 'norEduOrgUnitUniqueIdentifier': DEF+'norEduOrgUnitUniqueIdentifier', + 'norEduOrgUnitUniqueNumber': DEF+'norEduOrgUnitUniqueNumber', + 'norEduPersonBirthDate': DEF+'norEduPersonBirthDate', + 'norEduPersonLIN': DEF+'norEduPersonLIN', + 'norEduPersonNIN': DEF+'norEduPersonNIN', + 'o': DEF+'o', + 'objectClass': DEF+'objectClass', + 'organizationName': DEF+'organizationName', + 'organizationalStatus': DEF+'organizationalStatus', + 'organizationalUnitName': DEF+'organizationalUnitName', + 'otherMailbox': DEF+'otherMailbox', + 'ou': DEF+'ou', + 'owner': DEF+'owner', + 'pager': DEF+'pager', + 'pagerTelephoneNumber': DEF+'pagerTelephoneNumber', + 'personalSignature': DEF+'personalSignature', + 'personalTitle': DEF+'personalTitle', + 'photo': DEF+'photo', + 'physicalDeliveryOfficeName': DEF+'physicalDeliveryOfficeName', + 'pkcs9email': DEF+'pkcs9email', + 'postOfficeBox': DEF+'postOfficeBox', + 'postalAddress': DEF+'postalAddress', + 'postalCode': DEF+'postalCode', + 'preferredDeliveryMethod': DEF+'preferredDeliveryMethod', + 'preferredLanguage': DEF+'preferredLanguage', + 'presentationAddress': DEF+'presentationAddress', + 'protocolInformation': DEF+'protocolInformation', + 'pseudonym': DEF+'pseudonym', + 'registeredAddress': DEF+'registeredAddress', + 'rfc822Mailbox': DEF+'rfc822Mailbox', + 'roleOccupant': DEF+'roleOccupant', + 'roomNumber': DEF+'roomNumber', + 'sOARecord': DEF+'sOARecord', + 'searchGuide': DEF+'searchGuide', + 'secretary': DEF+'secretary', + 'seeAlso': DEF+'seeAlso', + 'serialNumber': DEF+'serialNumber', + 'singleLevelQuality': DEF+'singleLevelQuality', + 'sn': DEF+'sn', + 'st': DEF+'st', + 'stateOrProvinceName': DEF+'stateOrProvinceName', + 'street': DEF+'street', + 'streetAddress': DEF+'streetAddress', + 'subtreeMaximumQuality': DEF+'subtreeMaximumQuality', + 'subtreeMinimumQuality': DEF+'subtreeMinimumQuality', + 'supportedAlgorithms': DEF+'supportedAlgorithms', + 'supportedApplicationContext': DEF+'supportedApplicationContext', + 'surname': DEF+'surname', + 'telephoneNumber': DEF+'telephoneNumber', + 'teletexTerminalIdentifier': DEF+'teletexTerminalIdentifier', + 'telexNumber': DEF+'telexNumber', + 'textEncodedORAddress': DEF+'textEncodedORAddress', + 'title': DEF+'title', + 'uid': DEF+'uid', + 'uniqueIdentifier': DEF+'uniqueIdentifier', + 'uniqueMember': DEF+'uniqueMember', + 'userCertificate': DEF+'userCertificate', + 'userClass': DEF+'userClass', + 'userPKCS12': DEF+'userPKCS12', + 'userPassword': DEF+'userPassword', + 'userSMIMECertificate': DEF+'userSMIMECertificate', + 'userid': DEF+'userid', + 'x121Address': DEF+'x121Address', + 'x500UniqueIdentifier': DEF+'x500UniqueIdentifier', + } +} diff --git a/backend/attribute-maps/saml_uri.py b/backend/attribute-maps/saml_uri.py new file mode 100644 index 0000000..3a61726 --- /dev/null +++ b/backend/attribute-maps/saml_uri.py @@ -0,0 +1,316 @@ +EDUCOURSE_OID = 'urn:oid:1.3.6.1.4.1.5923.1.6.1.' +EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.' +EDUMEMBER1_OID = 'urn:oid:1.3.6.1.4.1.5923.1.5.1.' +LDAPGVAT_OID = 'urn:oid:1.2.40.0.10.2.1.1.' # ldap.gv.at definitions as specified in http://www.ref.gv.at/AG-IZ-PVP2-Version-2-1-0-2.2754.0.html +UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.' +X500ATTR_OID = 'urn:oid:2.5.4.' +LDAPGVAT_UCL_DIR_PILOT = UCL_DIR_PILOT +LDAPGVAT_X500ATTR_OID = X500ATTR_OID +NETSCAPE_LDAP = 'urn:oid:2.16.840.1.113730.3.1.' +NOREDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.2428.90.1.' +PKCS_9 = 'urn:oid:1.2.840.113549.1.9.1.' +SCHAC = 'urn:oid:1.3.6.1.4.1.25178.1.2.' +SIS = 'urn:oid:1.2.752.194.10.2.' +UMICH = 'urn:oid:1.3.6.1.4.1.250.1.57.' +OPENOSI_OID = 'urn:oid:1.3.6.1.4.1.27630.2.1.1.' #openosi-0.82.schema http://www.openosi.org/osi/display/ldap/Home +BREDUPERSON_OID_1 = 'urn:oid:1.3.6.1.4.1.15996.100.1.1.1.' # from rnp brPersonCPF +BREDUPERSON_OID_2 = 'urn:oid:1.3.6.1.4.1.15996.100.1.1.2.' # from rnp brEduAffiliationType +LDAPELEMENTS = 'urn:oid:1.3.6.1.4.1.1466.115.121.1.' # from ldap elementes http://www.oid-info.com/get/1.3.6.1.4.1.1466.115.121.1 + +MAP = { + 'identifier': 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', + 'fro': { + LDAPELEMENTS+'36': 'schacDateOfBirth', + BREDUPERSON_OID_1+'1': 'brPersonCPF', + BREDUPERSON_OID_2+'1': 'brEduAffiliationType', + EDUCOURSE_OID+'1': 'eduCourseOffering', + EDUCOURSE_OID+'2': 'eduCourseMember', + EDUMEMBER1_OID+'1': 'isMemberOf', + EDUPERSON_OID+'1': 'eduPersonAffiliation', + EDUPERSON_OID+'2': 'eduPersonNickname', + EDUPERSON_OID+'3': 'eduPersonOrgDN', + EDUPERSON_OID+'4': 'eduPersonOrgUnitDN', + EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation', + EDUPERSON_OID+'6': 'eduPersonPrincipalName', + EDUPERSON_OID+'7': 'eduPersonEntitlement', + EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN', + EDUPERSON_OID+'9': 'eduPersonScopedAffiliation', + EDUPERSON_OID+'10': 'eduPersonTargetedID', + EDUPERSON_OID+'11': 'eduPersonAssurance', + EDUPERSON_OID+'12': 'eduPersonPrincipalNamePrior', + EDUPERSON_OID+'13': 'eduPersonUniqueId', + EDUPERSON_OID+'16': 'eduPersonOrcid', + LDAPGVAT_OID+'1': 'PVP-GID', + LDAPGVAT_OID+'149': 'PVP-BPK', + LDAPGVAT_OID+'153': 'PVP-OU-OKZ', + LDAPGVAT_OID+'261.10': 'PVP-VERSION', + LDAPGVAT_OID+'261.20': 'PVP-PRINCIPAL-NAME', + LDAPGVAT_OID+'261.24': 'PVP-PARTICIPANT-OKZ', + LDAPGVAT_OID+'261.30': 'PVP-ROLES', + LDAPGVAT_OID+'261.40': 'PVP-INVOICE-RECPT-ID', + LDAPGVAT_OID+'261.50': 'PVP-COST-CENTER-ID', + LDAPGVAT_OID+'261.60': 'PVP-CHARGE-CODE', + LDAPGVAT_OID+'3': 'PVP-OU-GV-OU-ID', + LDAPGVAT_OID+'33': 'PVP-FUNCTION', + LDAPGVAT_OID+'55': 'PVP-BIRTHDATE', + LDAPGVAT_OID+'71': 'PVP-PARTICIPANT-ID', + LDAPGVAT_UCL_DIR_PILOT+'1': 'PVP-USERID', + LDAPGVAT_UCL_DIR_PILOT+'3': 'PVP-MAIL', + LDAPGVAT_X500ATTR_OID+'11': 'PVP-OU', + LDAPGVAT_X500ATTR_OID+'20': 'PVP-TEL', + LDAPGVAT_X500ATTR_OID+'42': 'PVP-GIVENNAME', + NETSCAPE_LDAP+'1': 'carLicense', + NETSCAPE_LDAP+'2': 'departmentNumber', + NETSCAPE_LDAP+'3': 'employeeNumber', + NETSCAPE_LDAP+'4': 'employeeType', + NETSCAPE_LDAP+'39': 'preferredLanguage', + NETSCAPE_LDAP+'40': 'userSMIMECertificate', + NETSCAPE_LDAP+'216': 'userPKCS12', + NETSCAPE_LDAP+'241': 'displayName', + NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber', + NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber', + NOREDUPERSON_OID+'3': 'norEduPersonBirthDate', + NOREDUPERSON_OID+'4': 'norEduPersonLIN', + NOREDUPERSON_OID+'5': 'norEduPersonNIN', + NOREDUPERSON_OID+'6': 'norEduOrgAcronym', + NOREDUPERSON_OID+'7': 'norEduOrgUniqueIdentifier', + NOREDUPERSON_OID+'8': 'norEduOrgUnitUniqueIdentifier', + NOREDUPERSON_OID+'9': 'federationFeideSchemaVersion', + NOREDUPERSON_OID+'10': 'norEduPersonLegalName', + NOREDUPERSON_OID+'11': 'norEduOrgSchemaVersion', + NOREDUPERSON_OID+'12': 'norEduOrgNIN', + OPENOSI_OID+'17': 'osiHomeUrl', + OPENOSI_OID+'19': 'osiPreferredTZ', + OPENOSI_OID+'72': 'osiICardTimeLastUpdated', + OPENOSI_OID+'104': 'osiMiddleName', + OPENOSI_OID+'107': 'osiOtherEmail', + OPENOSI_OID+'109': 'osiOtherHomePhone', + OPENOSI_OID+'120': 'osiWorkURL', + PKCS_9+'1': 'email', + SCHAC+'1': 'schacMotherTongue', + SCHAC+'2': 'schacGender', + SCHAC+'3': 'schacDateOfBirth', + SCHAC+'4': 'schacPlaceOfBirth', + SCHAC+'5': 'schacCountryOfCitizenship', + SCHAC+'6': 'schacSn1', + SCHAC+'7': 'schacSn2', + SCHAC+'8': 'schacPersonalTitle', + SCHAC+'9': 'schacHomeOrganization', + SCHAC+'10': 'schacHomeOrganizationType', + SCHAC+'11': 'schacCountryOfResidence', + SCHAC+'12': 'schacUserPresenceID', + SCHAC+'13': 'schacPersonalPosition', + SCHAC+'14': 'schacPersonalUniqueCode', + SCHAC+'15': 'schacPersonalUniqueID', + SCHAC+'17': 'schacExpiryDate', + SCHAC+'18': 'schacUserPrivateAttribute', + SCHAC+'19': 'schacUserStatus', + SCHAC+'20': 'schacProjectMembership', + SCHAC+'21': 'schacProjectSpecificRole', + SIS+'1': 'sisLegalGuardianFor', + SIS+'2': 'sisSchoolGrade', + UCL_DIR_PILOT+'1': 'uid', + UCL_DIR_PILOT+'3': 'mail', + UCL_DIR_PILOT+'25': 'dc', + UCL_DIR_PILOT+'37': 'associatedDomain', + UCL_DIR_PILOT+'43': 'co', + UCL_DIR_PILOT+'60': 'jpegPhoto', + UMICH+'57': 'labeledURI', + X500ATTR_OID+'2': 'knowledgeInformation', + X500ATTR_OID+'3': 'cn', + X500ATTR_OID+'4': 'sn', + X500ATTR_OID+'5': 'serialNumber', + X500ATTR_OID+'6': 'c', + X500ATTR_OID+'7': 'l', + X500ATTR_OID+'8': 'st', + X500ATTR_OID+'9': 'street', + X500ATTR_OID+'10': 'o', + X500ATTR_OID+'11': 'ou', + X500ATTR_OID+'12': 'title', + X500ATTR_OID+'14': 'searchGuide', + X500ATTR_OID+'15': 'businessCategory', + X500ATTR_OID+'16': 'postalAddress', + X500ATTR_OID+'17': 'postalCode', + X500ATTR_OID+'18': 'postOfficeBox', + X500ATTR_OID+'19': 'physicalDeliveryOfficeName', + X500ATTR_OID+'20': 'telephoneNumber', + X500ATTR_OID+'21': 'telexNumber', + X500ATTR_OID+'22': 'teletexTerminalIdentifier', + X500ATTR_OID+'23': 'facsimileTelephoneNumber', + X500ATTR_OID+'24': 'x121Address', + X500ATTR_OID+'25': 'internationaliSDNNumber', + X500ATTR_OID+'26': 'registeredAddress', + X500ATTR_OID+'27': 'destinationIndicator', + X500ATTR_OID+'28': 'preferredDeliveryMethod', + X500ATTR_OID+'29': 'presentationAddress', + X500ATTR_OID+'30': 'supportedApplicationContext', + X500ATTR_OID+'31': 'member', + X500ATTR_OID+'32': 'owner', + X500ATTR_OID+'33': 'roleOccupant', + X500ATTR_OID+'36': 'userCertificate', + X500ATTR_OID+'37': 'cACertificate', + X500ATTR_OID+'38': 'authorityRevocationList', + X500ATTR_OID+'39': 'certificateRevocationList', + X500ATTR_OID+'40': 'crossCertificatePair', + X500ATTR_OID+'42': 'givenName', + X500ATTR_OID+'43': 'initials', + X500ATTR_OID+'44': 'generationQualifier', + X500ATTR_OID+'45': 'x500UniqueIdentifier', + X500ATTR_OID+'46': 'dnQualifier', + X500ATTR_OID+'47': 'enhancedSearchGuide', + X500ATTR_OID+'48': 'protocolInformation', + X500ATTR_OID+'50': 'uniqueMember', + X500ATTR_OID+'51': 'houseIdentifier', + X500ATTR_OID+'52': 'supportedAlgorithms', + X500ATTR_OID+'53': 'deltaRevocationList', + X500ATTR_OID+'54': 'dmdName', + X500ATTR_OID+'65': 'pseudonym', + }, + 'to': { + 'schacDateOfBirth': LDAPELEMENTS+'36', + 'associatedDomain': UCL_DIR_PILOT+'37', + 'authorityRevocationList': X500ATTR_OID+'38', + 'brEduAffiliationType': BREDUPERSON_OID_2+'1', + 'brPersonCPF': BREDUPERSON_OID_1+'1', + 'businessCategory': X500ATTR_OID+'15', + 'c': X500ATTR_OID+'6', + 'cACertificate': X500ATTR_OID+'37', + 'carLicense': NETSCAPE_LDAP+'1', + 'certificateRevocationList': X500ATTR_OID+'39', + 'cn': X500ATTR_OID+'3', + 'co': UCL_DIR_PILOT+'43', + 'crossCertificatePair': X500ATTR_OID+'40', + 'dc': UCL_DIR_PILOT+'25', + 'deltaRevocationList': X500ATTR_OID+'53', + 'departmentNumber': NETSCAPE_LDAP+'2', + 'destinationIndicator': X500ATTR_OID+'27', + 'displayName': NETSCAPE_LDAP+'241', + 'dmdName': X500ATTR_OID+'54', + 'dnQualifier': X500ATTR_OID+'46', + 'eduCourseMember': EDUCOURSE_OID+'2', + 'eduCourseOffering': EDUCOURSE_OID+'1', + 'eduPersonAffiliation': EDUPERSON_OID+'1', + 'eduPersonEntitlement': EDUPERSON_OID+'7', + 'eduPersonNickname': EDUPERSON_OID+'2', + 'eduPersonOrgDN': EDUPERSON_OID+'3', + 'eduPersonOrgUnitDN': EDUPERSON_OID+'4', + 'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5', + 'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8', + 'eduPersonPrincipalName': EDUPERSON_OID+'6', + 'eduPersonPrincipalNamePrior': EDUPERSON_OID+'12', + 'eduPersonScopedAffiliation': EDUPERSON_OID+'9', + 'eduPersonTargetedID': EDUPERSON_OID+'10', + 'eduPersonAssurance': EDUPERSON_OID+'11', + 'eduPersonUniqueId': EDUPERSON_OID+'13', + 'eduPersonOrcid': EDUPERSON_OID+'16', + 'email': PKCS_9+'1', + 'employeeNumber': NETSCAPE_LDAP+'3', + 'employeeType': NETSCAPE_LDAP+'4', + 'enhancedSearchGuide': X500ATTR_OID+'47', + 'facsimileTelephoneNumber': X500ATTR_OID+'23', + 'federationFeideSchemaVersion': NOREDUPERSON_OID+'9', + 'generationQualifier': X500ATTR_OID+'44', + 'givenName': X500ATTR_OID+'42', + 'houseIdentifier': X500ATTR_OID+'51', + 'initials': X500ATTR_OID+'43', + 'internationaliSDNNumber': X500ATTR_OID+'25', + 'isMemberOf': EDUMEMBER1_OID+'1', + 'jpegPhoto': UCL_DIR_PILOT+'60', + 'knowledgeInformation': X500ATTR_OID+'2', + 'l': X500ATTR_OID+'7', + 'labeledURI': UMICH+'57', + 'mail': UCL_DIR_PILOT+'3', + 'member': X500ATTR_OID+'31', + 'norEduOrgAcronym': NOREDUPERSON_OID+'6', + 'norEduOrgNIN': NOREDUPERSON_OID+'12', + 'norEduOrgSchemaVersion': NOREDUPERSON_OID+'11', + 'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7', + 'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1', + 'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8', + 'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2', + 'norEduPersonBirthDate': NOREDUPERSON_OID+'3', + 'norEduPersonLIN': NOREDUPERSON_OID+'4', + 'norEduPersonLegalName': NOREDUPERSON_OID+'10', + 'norEduPersonNIN': NOREDUPERSON_OID+'5', + 'o': X500ATTR_OID+'10', + 'osiHomeUrl': OPENOSI_OID+'17', + 'osiPreferredTZ': OPENOSI_OID+'19', + 'osiICardTimeLastUpdated': OPENOSI_OID+'72', + 'osiMiddleName': OPENOSI_OID+'104', + 'osiOtherEmail': OPENOSI_OID+'107', + 'osiOtherHomePhone': OPENOSI_OID+'109', + 'osiWorkURL': OPENOSI_OID+'120', + 'ou': X500ATTR_OID+'11', + 'owner': X500ATTR_OID+'32', + 'physicalDeliveryOfficeName': X500ATTR_OID+'19', + 'postOfficeBox': X500ATTR_OID+'18', + 'postalAddress': X500ATTR_OID+'16', + 'postalCode': X500ATTR_OID+'17', + 'preferredDeliveryMethod': X500ATTR_OID+'28', + 'preferredLanguage': NETSCAPE_LDAP+'39', + 'presentationAddress': X500ATTR_OID+'29', + 'protocolInformation': X500ATTR_OID+'48', + 'pseudonym': X500ATTR_OID+'65', + 'PVP-USERID': LDAPGVAT_UCL_DIR_PILOT+'1', + 'PVP-MAIL': LDAPGVAT_UCL_DIR_PILOT+'3', + 'PVP-GID': LDAPGVAT_OID+'1', + 'PVP-BPK': LDAPGVAT_OID+'149', + 'PVP-OU-OKZ': LDAPGVAT_OID+'153', + 'PVP-VERSION': LDAPGVAT_OID+'261.10', + 'PVP-PRINCIPAL-NAME': LDAPGVAT_OID+'261.20', + 'PVP-PARTICIPANT-OKZ': LDAPGVAT_OID+'261.24', + 'PVP-ROLES': LDAPGVAT_OID+'261.30', + 'PVP-INVOICE-RECPT-ID': LDAPGVAT_OID+'261.40', + 'PVP-COST-CENTER-ID': LDAPGVAT_OID+'261.50', + 'PVP-CHARGE-CODE': LDAPGVAT_OID+'261.60', + 'PVP-OU-GV-OU-ID': LDAPGVAT_OID+'3', + 'PVP-FUNCTION': LDAPGVAT_OID+'33', + 'PVP-BIRTHDATE': LDAPGVAT_OID+'55', + 'PVP-PARTICIPANT-ID': LDAPGVAT_OID+'71', + 'PVP-OU': LDAPGVAT_X500ATTR_OID+'11', + 'PVP-TEL': LDAPGVAT_X500ATTR_OID+'20', + 'PVP-GIVENNAME': LDAPGVAT_X500ATTR_OID+'42', + 'registeredAddress': X500ATTR_OID+'26', + 'roleOccupant': X500ATTR_OID+'33', + 'schacCountryOfCitizenship': SCHAC+'5', + 'schacCountryOfResidence': SCHAC+'11', + 'schacDateOfBirth': SCHAC+'3', + 'schacExpiryDate': SCHAC+'17', + 'schacGender': SCHAC+'2', + 'schacHomeOrganization': SCHAC+'9', + 'schacHomeOrganizationType': SCHAC+'10', + 'schacMotherTongue': SCHAC+'1', + 'schacPersonalPosition': SCHAC+'13', + 'schacPersonalTitle': SCHAC+'8', + 'schacPersonalUniqueCode': SCHAC+'14', + 'schacPersonalUniqueID': SCHAC+'15', + 'schacPlaceOfBirth': SCHAC+'4', + 'schacProjectMembership': SCHAC+'20', + 'schacProjectSpecificRole': SCHAC+'21', + 'schacSn1': SCHAC+'6', + 'schacSn2': SCHAC+'7', + 'schacUserPresenceID': SCHAC+'12', + 'schacUserPrivateAttribute': SCHAC+'18', + 'schacUserStatus': SCHAC+'19', + 'searchGuide': X500ATTR_OID+'14', + 'serialNumber': X500ATTR_OID+'5', + 'sisLegalGuardianFor': SIS+'1', + 'sisSchoolGrade': SIS+'2', + 'sn': X500ATTR_OID+'4', + 'st': X500ATTR_OID+'8', + 'street': X500ATTR_OID+'9', + 'supportedAlgorithms': X500ATTR_OID+'52', + 'supportedApplicationContext': X500ATTR_OID+'30', + 'telephoneNumber': X500ATTR_OID+'20', + 'teletexTerminalIdentifier': X500ATTR_OID+'22', + 'telexNumber': X500ATTR_OID+'21', + 'title': X500ATTR_OID+'12', + 'uid': UCL_DIR_PILOT+'1', + 'uniqueMember': X500ATTR_OID+'50', + 'userCertificate': X500ATTR_OID+'36', + 'userPKCS12': NETSCAPE_LDAP+'216', + 'userSMIMECertificate': NETSCAPE_LDAP+'40', + 'x121Address': X500ATTR_OID+'24', + 'x500UniqueIdentifier': X500ATTR_OID+'45', + } +} diff --git a/backend/attribute-maps/shibboleth_uri.py b/backend/attribute-maps/shibboleth_uri.py new file mode 100644 index 0000000..54de473 --- /dev/null +++ b/backend/attribute-maps/shibboleth_uri.py @@ -0,0 +1,197 @@ +EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.' +NETSCAPE_LDAP = 'urn:oid:2.16.840.1.113730.3.1.' +NOREDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.2428.90.1.' +PKCS_9 = 'urn:oid:1.2.840.113549.1.9.' +UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.' +UMICH = 'urn:oid:1.3.6.1.4.1.250.1.57.' +X500ATTR = 'urn:oid:2.5.4.' + + +MAP = { + "identifier": "urn:mace:shibboleth:1.0:attributeNamespace:uri", + 'fro': { + EDUPERSON_OID+'1': 'eduPersonAffiliation', + EDUPERSON_OID+'2': 'eduPersonNickname', + EDUPERSON_OID+'3': 'eduPersonOrgDN', + EDUPERSON_OID+'4': 'eduPersonOrgUnitDN', + EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation', + EDUPERSON_OID+'6': 'eduPersonPrincipalName', + EDUPERSON_OID+'7': 'eduPersonEntitlement', + EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN', + EDUPERSON_OID+'9': 'eduPersonScopedAffiliation', + EDUPERSON_OID+'10': 'eduPersonTargetedID', + EDUPERSON_OID+'11': 'eduPersonAssurance', + EDUPERSON_OID+'12': 'eduPersonPrincipalNamePrior', + EDUPERSON_OID+'13': 'eduPersonUniqueId', + EDUPERSON_OID+'16': 'eduPersonOrcid', + NETSCAPE_LDAP+'1': 'carLicense', + NETSCAPE_LDAP+'2': 'departmentNumber', + NETSCAPE_LDAP+'3': 'employeeNumber', + NETSCAPE_LDAP+'4': 'employeeType', + NETSCAPE_LDAP+'39': 'preferredLanguage', + NETSCAPE_LDAP+'40': 'userSMIMECertificate', + NETSCAPE_LDAP+'216': 'userPKCS12', + NETSCAPE_LDAP+'241': 'displayName', + NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber', + NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber', + NOREDUPERSON_OID+'3': 'norEduPersonBirthDate', + NOREDUPERSON_OID+'4': 'norEduPersonLIN', + NOREDUPERSON_OID+'5': 'norEduPersonNIN', + NOREDUPERSON_OID+'6': 'norEduOrgAcronym', + NOREDUPERSON_OID+'7': 'norEduOrgUniqueIdentifier', + NOREDUPERSON_OID+'8': 'norEduOrgUnitUniqueIdentifier', + NOREDUPERSON_OID+'9': 'federationFeideSchemaVersion', + PKCS_9+'1': 'email', + UCL_DIR_PILOT+'3': 'mail', + UCL_DIR_PILOT+'25': 'dc', + UCL_DIR_PILOT+'37': 'associatedDomain', + UCL_DIR_PILOT+'60': 'jpegPhoto', + X500ATTR+'2': 'knowledgeInformation', + X500ATTR+'4': 'sn', + X500ATTR+'5': 'serialNumber', + X500ATTR+'6': 'c', + X500ATTR+'7': 'l', + X500ATTR+'8': 'st', + X500ATTR+'9': 'street', + X500ATTR+'10': 'o', + X500ATTR+'11': 'ou', + X500ATTR+'12': 'title', + X500ATTR+'14': 'searchGuide', + X500ATTR+'15': 'businessCategory', + X500ATTR+'16': 'postalAddress', + X500ATTR+'17': 'postalCode', + X500ATTR+'18': 'postOfficeBox', + X500ATTR+'19': 'physicalDeliveryOfficeName', + X500ATTR+'20': 'telephoneNumber', + X500ATTR+'21': 'telexNumber', + X500ATTR+'22': 'teletexTerminalIdentifier', + X500ATTR+'23': 'facsimileTelephoneNumber', + X500ATTR+'24': 'x121Address', + X500ATTR+'25': 'internationaliSDNNumber', + X500ATTR+'26': 'registeredAddress', + X500ATTR+'27': 'destinationIndicator', + X500ATTR+'28': 'preferredDeliveryMethod', + X500ATTR+'29': 'presentationAddress', + X500ATTR+'30': 'supportedApplicationContext', + X500ATTR+'31': 'member', + X500ATTR+'32': 'owner', + X500ATTR+'33': 'roleOccupant', + X500ATTR+'36': 'userCertificate', + X500ATTR+'37': 'cACertificate', + X500ATTR+'38': 'authorityRevocationList', + X500ATTR+'39': 'certificateRevocationList', + X500ATTR+'40': 'crossCertificatePair', + X500ATTR+'42': 'givenName', + X500ATTR+'43': 'initials', + X500ATTR+'44': 'generationQualifier', + X500ATTR+'45': 'x500UniqueIdentifier', + X500ATTR+'46': 'dnQualifier', + X500ATTR+'47': 'enhancedSearchGuide', + X500ATTR+'48': 'protocolInformation', + X500ATTR+'50': 'uniqueMember', + X500ATTR+'51': 'houseIdentifier', + X500ATTR+'52': 'supportedAlgorithms', + X500ATTR+'53': 'deltaRevocationList', + X500ATTR+'54': 'dmdName', + X500ATTR+'65': 'pseudonym', + }, + 'to': { + 'associatedDomain': UCL_DIR_PILOT+'37', + 'authorityRevocationList': X500ATTR+'38', + 'businessCategory': X500ATTR+'15', + 'c': X500ATTR+'6', + 'cACertificate': X500ATTR+'37', + 'carLicense': NETSCAPE_LDAP+'1', + 'certificateRevocationList': X500ATTR+'39', + 'countryName': X500ATTR+'6', + 'crossCertificatePair': X500ATTR+'40', + 'dc': UCL_DIR_PILOT+'25', + 'deltaRevocationList': X500ATTR+'53', + 'departmentNumber': NETSCAPE_LDAP+'2', + 'destinationIndicator': X500ATTR+'27', + 'displayName': NETSCAPE_LDAP+'241', + 'dmdName': X500ATTR+'54', + 'dnQualifier': X500ATTR+'46', + 'domainComponent': UCL_DIR_PILOT+'25', + 'eduPersonAffiliation': EDUPERSON_OID+'1', + 'eduPersonEntitlement': EDUPERSON_OID+'7', + 'eduPersonNickname': EDUPERSON_OID+'2', + 'eduPersonOrgDN': EDUPERSON_OID+'3', + 'eduPersonOrgUnitDN': EDUPERSON_OID+'4', + 'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5', + 'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8', + 'eduPersonPrincipalName': EDUPERSON_OID+'6', + 'eduPersonPrincipalNamePrior': EDUPERSON_OID+'12', + 'eduPersonScopedAffiliation': EDUPERSON_OID+'9', + 'eduPersonTargetedID': EDUPERSON_OID+'10', + 'eduPersonAssurance': EDUPERSON_OID+'11', + 'eduPersonUniqueId': EDUPERSON_OID+'13', + 'eduPersonOrcid': EDUPERSON_OID+'16', + 'email': PKCS_9+'1', + 'emailAddress': PKCS_9+'1', + 'employeeNumber': NETSCAPE_LDAP+'3', + 'employeeType': NETSCAPE_LDAP+'4', + 'enhancedSearchGuide': X500ATTR+'47', + 'facsimileTelephoneNumber': X500ATTR+'23', + 'fax': X500ATTR+'23', + 'federationFeideSchemaVersion': NOREDUPERSON_OID+'9', + 'generationQualifier': X500ATTR+'44', + 'givenName': X500ATTR+'42', + 'gn': X500ATTR+'42', + 'houseIdentifier': X500ATTR+'51', + 'initials': X500ATTR+'43', + 'internationaliSDNNumber': X500ATTR+'25', + 'jpegPhoto': UCL_DIR_PILOT+'60', + 'knowledgeInformation': X500ATTR+'2', + 'l': X500ATTR+'7', + 'localityName': X500ATTR+'7', + 'mail': UCL_DIR_PILOT+'3', + 'member': X500ATTR+'31', + 'norEduOrgAcronym': NOREDUPERSON_OID+'6', + 'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7', + 'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1', + 'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8', + 'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2', + 'norEduPersonBirthDate': NOREDUPERSON_OID+'3', + 'norEduPersonLIN': NOREDUPERSON_OID+'4', + 'norEduPersonNIN': NOREDUPERSON_OID+'5', + 'o': X500ATTR+'10', + 'organizationName': X500ATTR+'10', + 'organizationalUnitName': X500ATTR+'11', + 'ou': X500ATTR+'11', + 'owner': X500ATTR+'32', + 'physicalDeliveryOfficeName': X500ATTR+'19', + 'pkcs9email': PKCS_9+'1', + 'postOfficeBox': X500ATTR+'18', + 'postalAddress': X500ATTR+'16', + 'postalCode': X500ATTR+'17', + 'preferredDeliveryMethod': X500ATTR+'28', + 'preferredLanguage': NETSCAPE_LDAP+'39', + 'presentationAddress': X500ATTR+'29', + 'protocolInformation': X500ATTR+'48', + 'pseudonym': X500ATTR+'65', + 'registeredAddress': X500ATTR+'26', + 'rfc822Mailbox': UCL_DIR_PILOT+'3', + 'roleOccupant': X500ATTR+'33', + 'searchGuide': X500ATTR+'14', + 'serialNumber': X500ATTR+'5', + 'sn': X500ATTR+'4', + 'st': X500ATTR+'8', + 'stateOrProvinceName': X500ATTR+'8', + 'street': X500ATTR+'9', + 'streetAddress': X500ATTR+'9', + 'supportedAlgorithms': X500ATTR+'52', + 'supportedApplicationContext': X500ATTR+'30', + 'surname': X500ATTR+'4', + 'telephoneNumber': X500ATTR+'20', + 'teletexTerminalIdentifier': X500ATTR+'22', + 'telexNumber': X500ATTR+'21', + 'title': X500ATTR+'12', + 'uniqueMember': X500ATTR+'50', + 'userCertificate': X500ATTR+'36', + 'userPKCS12': NETSCAPE_LDAP+'216', + 'userSMIMECertificate': NETSCAPE_LDAP+'40', + 'x121Address': X500ATTR+'24', + 'x500UniqueIdentifier': X500ATTR+'45', + } +} diff --git a/backend/core/saml2.py b/backend/core/saml2.py new file mode 100644 index 0000000..c1998b0 --- /dev/null +++ b/backend/core/saml2.py @@ -0,0 +1,40 @@ +import logging + +from django.contrib.auth.models import Group +from djangosaml2.backends import Saml2Backend + + +class ModifiedSaml2Backend(Saml2Backend): + + def _update_user(self, user, attributes: dict, attribute_mapping: dict, force_save: bool = False): + + log = logging.getLogger("saml") + + log.debug("USER: ", user) + log.debug("ATTRIBUTES: ", attributes) + + display_name = attributes.get('cn', [""])[0] + + if display_name: + names = display_name.split() + user.first_name = names[0] + user.last_name = names[-1] + user.profile.display_name = display_name + user.save() + + return super()._update_user(user, attributes, attribute_mapping, force_save) + + def save_user(self, user, *args, **kwargs): + log = logging.getLogger("saml") + user.save() + + try: + if not user.groups.filter(name="Saml2").exists(): + group, _ = Group.objects.get_or_create(name="Saml2") + group.user_set.add(user) + group.save() + log.debug("Added user to Saml2 group") + except Exception as _er: + log.error("Failed on add user to group Saml2. Error: %s" % _er) + + return super().save_user(user, *args, **kwargs) diff --git a/backend/core/shibboleth.py b/backend/core/shibboleth.py deleted file mode 100644 index b755521..0000000 --- a/backend/core/shibboleth.py +++ /dev/null @@ -1,62 +0,0 @@ -import logging - -from django.contrib.auth.models import Group -from shibboleth.middleware import ShibbolethRemoteUserMiddleware - - -class ShibbolethMiddleware(ShibbolethRemoteUserMiddleware): - def make_profile(self, user, shib_meta): - """ - This is here as a stub to allow subclassing of ShibbolethRemoteUserMiddleware - to include a make_profile method that will create a Django user profile - from the Shib provided attributes. By default it does nothing. - """ - log = logging.getLogger("shibboleth") - log.debug("Shib Meta:") - log.debug(shib_meta) - - log.debug("User:") - log.debug(user) - - # Guardar o email do usuario - if shib_meta.get("email", None): - user.email = shib_meta.get("email") - log.debug("Updated user email") - - if shib_meta.get("first_name", None): - fullname = shib_meta.get("first_name") - user.first_name = fullname.split()[0] - user.last_name = fullname.split()[-1] - - if user.profile.display_name != shib_meta.get("display_name", None): - user.profile.display_name = shib_meta.get("display_name", user.username) - log.debug("Added user profile display name") - user.profile.save() - - # Adiciona um display name para o usuario - if user.profile.display_name is None: - user.profile.display_name = user.username - user.profile.save() - - user.save() - - # Adicionar o usuario ao grupo Shibboleth - try: - if not user.groups.filter(name="Shibboleth").exists(): - group, created = Group.objects.get_or_create(name="Shibboleth") - group.user_set.add(user) - log.debug("Added user to Shibboleth group") - except Exception as e: - log.error("Failed on add user to group shibboleth. Error: %s" % e) - - return - - def setup_session(self, request): - """ - If you want to add custom code to setup user sessions, you - can extend this. - """ - log = logging.getLogger("shibboleth") - log.debug("---------- Setup Session ----------") - - return diff --git a/backend/core/shibboleth_urls.py b/backend/core/shibboleth_urls.py deleted file mode 100644 index 52c81ce..0000000 --- a/backend/core/shibboleth_urls.py +++ /dev/null @@ -1,12 +0,0 @@ -import django -from django.urls import re_path - -from shibboleth.views import ShibbolethView, ShibbolethLogoutView, ShibbolethLoginView - -app_name = "shibboleth" - -urlpatterns = [ - re_path(r"^login/$", ShibbolethLoginView.as_view(), name="login"), - re_path(r"^logout/$", ShibbolethLogoutView.as_view(), name="logout"), - re_path(r"^$", ShibbolethView.as_view(), name="info"), -] diff --git a/backend/pzserver/settings.py b/backend/pzserver/settings.py index 2e4ae38..b2643c6 100644 --- a/backend/pzserver/settings.py +++ b/backend/pzserver/settings.py @@ -12,6 +12,10 @@ import os +import saml2.saml + +import saml2 + # Build paths inside the project like this: BASE_DIR / 'subdir'. # BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -37,7 +41,6 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - # "django.contrib.sites", # Third-party "corsheaders", "django_filters", @@ -48,7 +51,7 @@ "oauth2_provider", "social_django", "drf_social_oauth2", - "shibboleth", + "djangosaml2", # Apps "core", ] @@ -59,7 +62,6 @@ "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", - "core.shibboleth.ShibbolethMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "corsheaders.middleware.CorsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", @@ -114,7 +116,6 @@ {"NAME": f"{auth_pass_str}.NumericPasswordValidator"}, ] - # Internationalization # https://docs.djangoproject.com/en/4.0/topics/i18n/ @@ -135,7 +136,6 @@ MEDIA_URL = "/archive/data/" MEDIA_ROOT = "/archive/data/" - # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field @@ -162,6 +162,7 @@ "drf_social_oauth2.authentication.SocialAuthentication", "rest_framework.authentication.TokenAuthentication", "rest_framework.authentication.SessionAuthentication", + # 'djangosaml2.backends.Saml2Backend', ), "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), "DEFAULT_FILTER_BACKENDS": [ @@ -184,45 +185,18 @@ JSON_EDITOR = True AUTHENTICATION_BACKENDS = ( - # "social_core.backends.github.GithubOAuth2", - # "social_core.backends.github.GithubOrganizationOAuth2", "drf_social_oauth2.backends.DjangoOAuth2", "django.contrib.auth.backends.ModelBackend", - "shibboleth.backends.ShibbolethRemoteUserBackend", + "core.saml2.ModifiedSaml2Backend", ) -# if os.getenv("GITHUB_CLIENT_ID", None) is not None: -# SOCIAL_AUTH_GITHUB_ORG_KEY = os.getenv("GITHUB_CLIENT_ID") -# SOCIAL_AUTH_GITHUB_ORG_SECRET = os.getenv("GITHUB_CLIENT_SECRET") -# SOCIAL_AUTH_GITHUB_ORG_NAME = os.getenv("GITHUB_ORG_NAME", "linea-it") -# SOCIAL_AUTH_GITHUB_ORG_SCOPE = ["user:email", "read:org"] -# SOCIAL_AUTH_JSONFIELD_ENABLED = True - ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = True LOGIN_REDIRECT_URL = "/" -# Shibboleth Authentication -SHIBBOLETH_ENABLED = False -if os.getenv("AUTH_SHIB_URL", None) is not None: - # https://github.com/Brown-University-Library/django-shibboleth-remoteuser - SHIBBOLETH_ATTRIBUTE_MAP = { - "eppn": (True, "username"), - "cn": (False, "first_name"), - "sn": (False, "display_name"), - "Shib-inetOrgPerson-mail": (False, "email"), - } - SHIBBOLETH_GROUP_ATTRIBUTES = "Shibboleth" - # Including Shibboleth authentication: - AUTHENTICATION_BACKENDS += ( - "shibboleth.backends.ShibbolethRemoteUserBackend",) - - SHIBBOLETH_ENABLED = True - OAUTH2_PROVIDER = { "ACCESS_TOKEN_EXPIRE_SECONDS": 36000, } - LOGGING = { "version": 1, "disable_existing_loggers": False, @@ -254,10 +228,10 @@ "backupCount": 5, "formatter": "standard", }, - "shibboleth": { + "saml": { "level": LOGGING_LEVEL, "class": "logging.handlers.RotatingFileHandler", - "filename": os.path.join(LOG_DIR, "shibboleth.log"), + "filename": os.path.join(LOG_DIR, "saml2.log"), "maxBytes": 1024 * 1024 * 5, # 5 MB "backupCount": 5, "formatter": "standard", @@ -287,8 +261,8 @@ "level": LOGGING_LEVEL, "propagate": True, }, - "shibboleth": { - "handlers": ["shibboleth"], + "saml": { + "handlers": ["saml"], "level": LOGGING_LEVEL, "propagate": True, }, @@ -299,3 +273,133 @@ }, }, } + +if os.getenv("AUTH_SHIB_URL", None): + FQDN = os.getenv("URI", "http://localhost") + CERT_DIR = "/saml2/certificates" + SIG_KEY_PEM = os.getenv("SIG_KEY_PEM", os.path.join(CERT_DIR, 'pzkey.pem')) + SIG_CERT_PEM = os.getenv("SIG_CERT_PEM", os.path.join(CERT_DIR, 'pzcert.pem')) + ENCRYP_KEY_PEM = os.getenv("ENCRYP_KEY_PEM", SIG_KEY_PEM) + ENCRYP_CERT_PEM = os.getenv("ENCRYP_CERT_PEM", SIG_CERT_PEM) + + MIDDLEWARE.append('djangosaml2.middleware.SamlSessionMiddleware') + + # configurações relativas ao session cookie + SAML_SESSION_COOKIE_NAME = 'saml_session' + SESSION_COOKIE_SECURE = True + + # Qualquer view que requer um usuário autenticado deve redirecionar o navegador para esta url + LOGIN_URL = '/saml2/login/' + + # Encerra a sessão quando o usuário fecha o navegador + SESSION_EXPIRE_AT_BROWSER_CLOSE = True + + # Tipo de binding utilizado + SAML_DEFAULT_BINDING = saml2.BINDING_HTTP_POST + SAML_IGNORE_LOGOUT_ERRORS = True + + # Serviço de descoberta da cafeexpresso + # SAML2_DISCO_URL = 'https://ds.cafeexpresso.rnp.br/WAYF.php' + + # Cria usuário Django a partir da asserção SAML caso o mesmo não exista + SAML_CREATE_UNKNOWN_USER = True + + # https://djangosaml2.readthedocs.io/contents/security.html#content-security-policy + SAML_CSP_HANDLER = "" + + # URL para redirecionamento após a autenticação + LOGIN_REDIRECT_URL = '/' + + SAML_ATTRIBUTE_MAPPING = { + "eduPersonPrincipalName": ("username",), + "sn": ("name",), + "cn": ("full_name",), + "email": ("email",) + } + + SAML_CONFIG = { + # Biblioteca usada para assinatura e criptografia + 'xmlsec_binary': '/usr/bin/xmlsec1', + 'entityid': FQDN + '/saml2/metadata/', + # Diretório contendo os esquemas de mapeamento de atributo + 'attribute_map_dir': os.path.join(BASE_DIR, 'attribute-maps'), + 'description': 'SP Pz Server', + 'service': { + 'sp' : { + 'name': 'sp_pzserver', + 'ui_info': { + 'display_name': {'text':'SP Pz', 'lang':'en'}, + 'description': {'text':'Pz Service Provider', 'lang':'en'}, + 'information_url': {'text': f"{FQDN}/about", 'lang':'en'}, + 'privacy_statement_url': {'text': FQDN, 'lang':'en'} + }, + 'name_id_format': [ + "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "urn:oasis:names:tc:SAML:2.0:nameid-format:transient", + ], + # Indica os endpoints dos serviços fornecidos + 'endpoints': { + 'assertion_consumer_service': [ + (FQDN +'/saml2/acs/', + saml2.BINDING_HTTP_POST), + ], + 'single_logout_service': [ + (FQDN + '/saml2/ls/', + saml2.BINDING_HTTP_REDIRECT), + (FQDN + '/saml2/ls/post', + saml2.BINDING_HTTP_POST), + ], + }, + # Algoritmos utilizados + #'signing_algorithm': saml2.xmldsig.SIG_RSA_SHA256, + #'digest_algorithm': saml2.xmldsig.DIGEST_SHA256, + + 'force_authn': False, + 'name_id_format_allow_create': False, + + # Indica que as respostas de autenticação para este SP devem ser assinadas + 'want_response_signed': True, + + # Indica se as solicitações de autenticação enviadas por este SP devem ser assinadas + 'authn_requests_signed': True, + + # Indica se este SP deseja que o IdP envie as asserções assinadas + 'want_assertions_signed': False, + + 'only_use_keys_in_metadata': True, + 'allow_unsolicited': False, + }, + }, + + # Indica onde os metadados podem ser encontrados + 'metadata': { + 'local': [os.getenv("IDP_METADATA")], + }, + + 'debug': os.getenv("DEBUG", 1), + + # Signature + 'key_file': SIG_KEY_PEM, # private part + 'cert_file': SIG_CERT_PEM, # public part + + # Encriptation + 'encryption_keypairs': [{ + 'key_file': ENCRYP_KEY_PEM, # private part + 'cert_file': ENCRYP_CERT_PEM, # public part + }], + + 'contact_person': [ + {'given_name': 'LIneA', + 'sur_name': 'Team', + 'company': 'LIneA', + 'email_address': 'itteam@linea.org.br', + 'contact_type': 'technical'}, + ], + + # Descreve a organização responsável pelo serviço + 'organization': { + 'name': [('LIneA', 'pt-br')], + 'display_name': [('LIneA', 'pt-br')], + 'url': [('https://linea.org.br/', 'pt-br')], + }, + } \ No newline at end of file diff --git a/backend/pzserver/urls.py b/backend/pzserver/urls.py index 9bbc18f..751f3c0 100644 --- a/backend/pzserver/urls.py +++ b/backend/pzserver/urls.py @@ -14,25 +14,14 @@ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ # from core.api import viewsets as products_viewsets -from core.views import ( - CsrfToOauth, - GetToken, - LoggedUserView, - Logout, - ProductContentViewSet, - ProductFileViewSet, - ProductTypeViewSet, - ProductViewSet, - ReleaseViewSet, - UserViewSet, -) +from core.views import (CsrfToOauth, GetToken, LoggedUserView, Logout, + ProductContentViewSet, ProductFileViewSet, + ProductTypeViewSet, ProductViewSet, ReleaseViewSet, + UserViewSet) from django.contrib import admin from django.urls import include, path -from drf_spectacular.views import ( - SpectacularAPIView, - SpectacularRedocView, - SpectacularSwaggerView, -) +from drf_spectacular.views import (SpectacularAPIView, SpectacularRedocView, + SpectacularSwaggerView) from rest_framework import routers route = routers.DefaultRouter() @@ -57,7 +46,6 @@ path("api/csrf_oauth/", CsrfToOauth.as_view()), path("api/logged_user/", LoggedUserView.as_view(), name="logged_user"), path("api/logout/", Logout.as_view(), name="logout"), - path("api/shib/", include("core.shibboleth_urls", namespace="shibboleth")), # API DOCs path("api/schema/", SpectacularAPIView.as_view(), name="schema"), path( @@ -66,4 +54,5 @@ name="swagger", ), path("api/redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"), + path(r"saml2/", include('djangosaml2.urls')), ] diff --git a/backend/requirements.txt b/backend/requirements.txt index b785cb4..0dd48f8 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -5,6 +5,8 @@ django-cors-headers==4.3.1 django-filebrowser-no-grappelli==4.0.2 django-filter==24.2 django-oauth-toolkit==2.3.0 +djangosaml2==1.9.3 +xmlsec==1.3.14 django-shibboleth-remoteuser==0.12 djangorestframework==3.15.1 drf-social-oauth2==2.2.0 diff --git a/docker-compose-development.yml b/docker-compose-development.yml index 3696fdd..734e43a 100644 --- a/docker-compose-development.yml +++ b/docker-compose-development.yml @@ -27,6 +27,7 @@ services: - ./backend:/app - ./archive/log/backend:/archive/log - ./archive/data:/archive/data + # - ./saml2:/saml2 # uncomment if authentication with github is required depends_on: - database diff --git a/env_template b/env_template index 37e913f..6e44ba0 100644 --- a/env_template +++ b/env_template @@ -1,4 +1,4 @@ -# Postgres +# Postgres POSTGRES_USER=pzadmin POSTGRES_PASSWORD=adminpz POSTGRES_DB=pzdev @@ -14,7 +14,7 @@ POSTGRES_DB=pzdev # SECURITY WARNING: don't run with debug turned on in production! DEBUG=1 LOGGING_LEVEL=DEBUG -# AUTORELOAD: Select 1 to enable auto reload and 0 to turn off. In production we must +# AUTORELOAD: Select 1 to enable auto reload and 0 to turn off. In production we must # disable it. AUTORELOAD=1 # SECURITY WARNING: keep the secret key used in production secret! @@ -28,9 +28,13 @@ DB_DATABASE=pzdev DB_HOST=database DB_PORT=5432 +# URI +DOMAIN=localhost +URI=http://${DOMAIN} + # CORS -DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] -DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost http://127.0.0.1 +DJANGO_ALLOWED_HOSTS=${DOMAIN} 127.0.0.1 [::1] +DJANGO_CSRF_TRUSTED_ORIGINS=${URI} http://127.0.0.1 # Frontend # Client ID e Client Secret devem ser cadastradas no Django Admin @@ -38,13 +42,15 @@ DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost http://127.0.0.1 # DJANGO_OAUTH_CLIENT_ID= # DJANGO_OAUTH_CLIENT_SECRET= -# Github OAuth -# To enable Github OAuth authentication, -# uncomment and fill in the following variables. -#GITHUB_CLIENT_ID= -#GITHUB_CLIENT_SECRET= -#GITHUB_ORG_NAME=linea-it +# Saml2 / Satosa Auth +# URL to login using satosa +# AUTH_SHIB_URL=${URI}/saml2/login/ + +# Keys and Certificates +# SIG_KEY_PEM= +# SIG_CERT_PEM= +# ENCRYP_KEY_PEM= +# ENCRYP_CERT_PEM= -# Shibboleth / Satosa Auth -# Url para login utilizando Shibboleth -# AUTH_SHIB_URL= \ No newline at end of file +# IDP metadata +# IDP_METADATA= \ No newline at end of file diff --git a/nginx_development.conf b/nginx_development.conf index 49d0f9c..1e75522 100644 --- a/nginx_development.conf +++ b/nginx_development.conf @@ -57,6 +57,11 @@ server { uwsgi_pass pzapi; } + location /saml2 { + include uwsgi_params; + uwsgi_pass pzapi; + } + location /admin { include uwsgi_params; uwsgi_pass pzapi; diff --git a/nginx_production.conf b/nginx_production.conf index a5a45af..8e02101 100644 --- a/nginx_production.conf +++ b/nginx_production.conf @@ -6,11 +6,6 @@ upstream pzfrontend { server frontend:3000; } -upstream shibserver { - ip_hash; - server gidlab:80; -} - server { @@ -69,23 +64,9 @@ server { autoindex off; } - # Shibboleth - location /Shibboleth.sso/ { - proxy_pass http://shibserver$request_uri; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Real-IP $remote_addr; - } - - # Shibboleth middleware - location /api/shib/ { - proxy_pass http://shibserver$request_uri; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Real-IP $remote_addr; + location /saml2 { + include uwsgi_params; + uwsgi_pass pzapi; } - }