From 3688cec91a69077df73f28ff3c65bfd59868c583 Mon Sep 17 00:00:00 2001 From: Neven1986 Date: Fri, 20 Dec 2019 03:24:26 +0100 Subject: [PATCH] Support for SAML metadata Requested Attributes Enhancements: - More robust check when creating self-signed certificates - Added support for SAML Requested Attributes through "SAML_SP_REQUESTED_ATTRIBUTES" parameter --- configs/development.py | 24 ++++++++++++++++++++++++ powerdnsadmin/services/saml.py | 27 ++++++++++++++++++++------- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/configs/development.py b/configs/development.py index b62d7c9..39c8f6d 100644 --- a/configs/development.py +++ b/configs/development.py @@ -44,6 +44,30 @@ SAML_ENABLED = False # ### Example: urn:oid:0.9.2342.19200300.100.1.1 # #SAML_NAMEID_FORMAT = 'urn:oid:0.9.2342.19200300.100.1.1' +# Following parameter defines RequestedAttributes section in SAML metadata +# since certain iDPs require explicit attribute request. If not provided section +# will not be available in metadata. +# +# Possible attributes: +# name (mandatory), nameFormat, isRequired, friendlyName +# +# NOTE: This parameter requires to be entered in valid JSON format as displayed below +# and multiple attributes can given +# +# Following example: +# +# SAML_SP_REQUESTED_ATTRIBUTES = '[ \ +# {"name": "urn:oid:0.9.2342.19200300.100.1.3", "nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "isRequired": true, "friendlyName": "email"}, \ +# {"name": "mail", "isRequired": false, "friendlyName": "test-field"} \ +# ]' +# +# produces following metadata section: +# +# +# +# + + # ## Attribute to use for Email address # ### Default: email # ### Example: urn:oid:0.9.2342.19200300.100.1.3 diff --git a/powerdnsadmin/services/saml.py b/powerdnsadmin/services/saml.py index cd2eb27..1114817 100644 --- a/powerdnsadmin/services/saml.py +++ b/powerdnsadmin/services/saml.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta from threading import Thread from flask import current_app +import json import os from ..lib.certutil import KEY_FILE, CERT_FILE, create_self_signed_cert @@ -117,14 +118,27 @@ class SAML(object): else: - create_self_signed_cert() - - if os.path.isfile(CERT_FILE): + if (os.path.isfile(CERT_FILE)) and (os.path.isfile(KEY_FILE)): cert = open(CERT_FILE, "r").readlines() - settings['sp']['x509cert'] = "".join(cert) - if os.path.isfile(KEY_FILE): key = open(KEY_FILE, "r").readlines() - settings['sp']['privateKey'] = "".join(key) + else: + create_self_signed_cert() + cert = open(CERT_FILE, "r").readlines() + key = open(KEY_FILE, "r").readlines() + + settings['sp']['x509cert'] = "".join(cert) + settings['sp']['privateKey'] = "".join(key) + + + if 'SAML_SP_REQUESTED_ATTRIBUTES' in current_app.config: + saml_req_attr = json.loads(current_app.config['SAML_SP_REQUESTED_ATTRIBUTES']) + settings['sp']['attributeConsumingService'] = { + "serviceName": "PowerDNSAdmin", + "serviceDescription": "PowerDNS-Admin - PowerDNS administration utility", + "requestedAttributes": saml_req_attr + } + else: + settings['sp']['attributeConsumingService'] = {} settings['sp']['assertionConsumerService'] = {} @@ -132,7 +146,6 @@ class SAML(object): 'binding'] = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' settings['sp']['assertionConsumerService'][ 'url'] = own_url + '/saml/authorized' - settings['sp']['attributeConsumingService'] = {} settings['sp']['singleLogoutService'] = {} settings['sp']['singleLogoutService'][ 'binding'] = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'