SAML Settings Help, Now catching SAML Errors gracefully.
This commit is contained in:
parent
d57a37e9c1
commit
c4fde72296
|
@ -1759,8 +1759,8 @@ def setting_authentication():
|
|||
'msg':
|
||||
'Saved successfully. Please reload PDA to take effect.'
|
||||
}
|
||||
global saml
|
||||
saml = SAML()
|
||||
# # Attempt to reinitialize SAML. If attempt fails, setting will be automatically disabled.
|
||||
# SAML()
|
||||
else:
|
||||
return abort(400)
|
||||
|
||||
|
|
|
@ -917,6 +917,8 @@ def saml_login():
|
|||
auth = saml.init_saml_auth(req)
|
||||
redirect_url = OneLogin_Saml2_Utils.get_self_url(req) + url_for(
|
||||
'index.saml_authorized')
|
||||
if auth is None:
|
||||
return render_template('errors/SAML.html')
|
||||
return redirect(auth.login(return_to=redirect_url))
|
||||
|
||||
|
||||
|
@ -928,8 +930,15 @@ def saml_metadata():
|
|||
|
||||
req = saml.prepare_flask_request(request)
|
||||
auth = saml.init_saml_auth(req)
|
||||
if auth is None:
|
||||
return render_template('errors/SAML.html')
|
||||
settings = auth.get_settings()
|
||||
try:
|
||||
metadata = settings.get_sp_metadata()
|
||||
except:
|
||||
current_app.logger.error(
|
||||
"SAML: Error fetching SP Metadata")
|
||||
return render_template('errors/SAML.html')
|
||||
errors = settings.validate_metadata(metadata)
|
||||
|
||||
if len(errors) == 0:
|
||||
|
@ -947,6 +956,8 @@ def saml_authorized():
|
|||
abort(400)
|
||||
req = saml.prepare_flask_request(request)
|
||||
auth = saml.init_saml_auth(req)
|
||||
if auth is None:
|
||||
return render_template('errors/SAML.html')
|
||||
auth.process_response()
|
||||
current_app.logger.debug( auth.get_attributes() )
|
||||
errors = auth.get_errors()
|
||||
|
@ -1147,8 +1158,13 @@ def uplift_to_admin(user):
|
|||
|
||||
@index_bp.route('/saml/sls')
|
||||
def saml_logout():
|
||||
if not Setting().get('saml_enabled'):
|
||||
current_app.logger.error("SAML authentication is disabled.")
|
||||
abort(400)
|
||||
req = saml.prepare_flask_request(request)
|
||||
auth = saml.init_saml_auth(req)
|
||||
if auth is None:
|
||||
return render_template('errors/SAML.html')
|
||||
url = auth.process_slo()
|
||||
errors = auth.get_errors()
|
||||
if len(errors) == 0:
|
||||
|
|
|
@ -25,7 +25,8 @@ class SAML(object):
|
|||
self.idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
|
||||
Setting().get('saml_metadata_url'),
|
||||
entity_id=Setting().get('saml_idp_entity_id'),
|
||||
required_sso_binding=Setting().get('saml_idp_sso_binding'))
|
||||
required_sso_binding=Setting().get('saml_idp_sso_binding'),
|
||||
required_slo_binding=Setting().get('saml_idp_slo_binding'))
|
||||
except:
|
||||
self.idp_data = None
|
||||
else:
|
||||
|
@ -36,23 +37,18 @@ class SAML(object):
|
|||
except:
|
||||
self.idp_data = None
|
||||
if self.idp_data is None:
|
||||
current_app.logger.info(
|
||||
current_app.logger.error(
|
||||
'SAML: IDP Metadata initial load failed')
|
||||
Setting().set('saml_enabled', False)
|
||||
print("SAML EN1 ", Setting().get('saml_enabled'))
|
||||
# exit(-1)
|
||||
|
||||
|
||||
def get_idp_data(self):
|
||||
|
||||
lifetime = timedelta(
|
||||
minutes=int(Setting().get('saml_metadata_cache_lifetime'))) # should be seconds instead of minutes?
|
||||
# Since SAML is now user-configurable, idp_data may change before the lifetime has ended,
|
||||
# so metadata should not be cached at all, or outdated settings may be used.
|
||||
try:
|
||||
minutes=int(Setting().get('saml_metadata_cache_lifetime')))
|
||||
if not hasattr(self,'idp_timestamp'):
|
||||
self.retrieve_idp_data()
|
||||
except:
|
||||
return None
|
||||
if self.idp_timestamp + lifetime < datetime.now():
|
||||
elif self.idp_timestamp + lifetime < datetime.now():
|
||||
background_thread = Thread(target=self.retrieve_idp_data())
|
||||
background_thread.start()
|
||||
|
||||
|
@ -165,9 +161,10 @@ class SAML(object):
|
|||
settings['sp']['singleLogoutService'][
|
||||
'binding'] = Setting().get('saml_idp_slo_binding')
|
||||
settings['sp']['singleLogoutService']['url'] = own_url + '/saml/sls'
|
||||
if metadata is not None and 'idp' in metadata:
|
||||
settings['idp'] = metadata['idp']
|
||||
settings['strict'] = True
|
||||
settings['debug'] = Setting().get('saml_debug')
|
||||
settings['debug'] = bool(Setting().get('saml_debug'))
|
||||
settings['security'] = {}
|
||||
settings['security'][
|
||||
'digestAlgorithm'] = Setting().get('saml_digest_algorithm')
|
||||
|
@ -176,17 +173,17 @@ class SAML(object):
|
|||
settings['security']['requestedAuthnContext'] = True
|
||||
settings['security'][
|
||||
'signatureAlgorithm'] = Setting().get('saml_signature_algorithm')
|
||||
settings['security']['wantAssertionsEncrypted'] = Setting().get('saml_want_assertions_encrypted')
|
||||
settings['security']['wantAssertionsEncrypted'] = bool(Setting().get('saml_want_assertions_encrypted'))
|
||||
settings['security']['wantAttributeStatement'] = True
|
||||
settings['security']['wantNameId'] = True
|
||||
settings['security']['authnRequestsSigned'] = Setting().get('saml_sign_authn_request')
|
||||
settings['security']['logoutRequestSigned'] = Setting().get('saml_sign_logout_request_response')
|
||||
settings['security']['logoutResponseSigned'] = Setting().get('saml_sign_logout_request_response')
|
||||
settings['security']['nameIdEncrypted'] = Setting().get('saml_nameid_encrypted')
|
||||
settings['security']['signMetadata'] = Setting().get('saml_sign_metadata')
|
||||
settings['security']['wantAssertionsSigned'] = Setting().get('saml_want_assertions_signed')
|
||||
settings['security']['wantMessagesSigned'] = Setting().get('saml_want_message_signed')
|
||||
settings['security']['wantNameIdEncrypted'] = Setting().get('saml_want_nameid_encrypted')
|
||||
settings['security']['authnRequestsSigned'] = bool(Setting().get('saml_sign_authn_request'))
|
||||
settings['security']['logoutRequestSigned'] = bool(Setting().get('saml_sign_logout_request_response'))
|
||||
settings['security']['logoutResponseSigned'] = bool(Setting().get('saml_sign_logout_request_response'))
|
||||
settings['security']['nameIdEncrypted'] = bool(Setting().get('saml_nameid_encrypted'))
|
||||
settings['security']['signMetadata'] = bool(Setting().get('saml_sign_metadata'))
|
||||
settings['security']['wantAssertionsSigned'] = bool(Setting().get('saml_want_assertions_signed'))
|
||||
settings['security']['wantMessagesSigned'] = bool(Setting().get('saml_want_message_signed'))
|
||||
settings['security']['wantNameIdEncrypted'] = bool(Setting().get('saml_want_nameid_encrypted'))
|
||||
settings['contactPerson'] = {}
|
||||
settings['contactPerson']['support'] = {}
|
||||
settings['contactPerson']['support']['emailAddress'] = Setting().get('saml_sp_contact_mail')
|
||||
|
@ -199,5 +196,10 @@ class SAML(object):
|
|||
settings['organization']['en-US']['displayname'] = 'PowerDNS-Admin'
|
||||
settings['organization']['en-US']['name'] = 'PowerDNS-Admin'
|
||||
settings['organization']['en-US']['url'] = own_url
|
||||
try:
|
||||
auth = self.OneLogin_Saml2_Auth(req, settings)
|
||||
except:
|
||||
current_app.logger.error(
|
||||
"SAML: SAML Authentication failed")
|
||||
auth = None
|
||||
return auth
|
||||
|
|
|
@ -810,7 +810,7 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" id="saml_want_assertions_signed" name="saml_want_assertions_signed" class="checkbox" {% if SETTING.get('saml_want_assertions_signed') %}checked{% endif %}>
|
||||
<label for="saml_want_assertions_encrypted">Want Assertions Signed</label>
|
||||
<label for="saml_want_assertions_signed">Want Assertions Signed</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" id="saml_want_message_signed" name="saml_want_message_signed" class="checkbox" {% if SETTING.get('saml_want_message_signed') %}checked{% endif %}>
|
||||
|
@ -822,7 +822,7 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" id="saml_want_nameid_encrypted" name="saml_want_nameid_encrypted" class="checkbox" {% if SETTING.get('saml_want_nameid_encrypted') %}checked{% endif %}>
|
||||
<label for="saml_want_message_signed">Want NameID Encrypted </label>
|
||||
<label for="saml_want_nameid_encrypted">Want NameID Encrypted</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="saml_digest_algorithm">Digest Algorithm</label>
|
||||
|
@ -900,32 +900,97 @@
|
|||
<div class="col-md-8">
|
||||
<legend>Help</legend>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>METADATA</dt>
|
||||
<dt>General</dt>
|
||||
<dd> <br>
|
||||
<b>Enable SAML</b> - Enables or disables SAML Authentication. <br>
|
||||
If toggled on, the following fields must be filled in the left form:
|
||||
<ul>
|
||||
<li>
|
||||
<b>Metadata URL</b> - URL to fetch metadata from
|
||||
<b>IDP Entity ID</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>Metadata Cache Lifetime</b> - Cache Lifetime in minutes before fresh metadata are requested
|
||||
<b>IDP Metadata URL</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>IDP SSO BINDING</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>IDP SLO BINDING</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Entity ID</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>SP NameID Format</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Requested Attributes</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>Cert File</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>Cert Key</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>Digest Algorithm</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>Signature Algorithm</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>Logout URL</b>, if <i>SAML Logout</i> is toggled on
|
||||
</li>
|
||||
<li>
|
||||
<b>Roles Provisioning Field</b> and <b>Urn Prefix</b>, if <i>Roles Autoprovisioning</i> is toggled on.
|
||||
</li>
|
||||
</ul>
|
||||
The rest can be filled, or left empty to revert to the Default settings.
|
||||
</dd>
|
||||
<dt>IDP</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
<b>IDP Entity ID</b> - EntityID of the IDP to use. Only needed if more than one IDP is in the SAML_METADATA_URL
|
||||
</li>
|
||||
<li>
|
||||
<b>IDP Metadata URL</b> - URL to fetch IDP metadata from
|
||||
</li>
|
||||
<li>
|
||||
<b>IDP Metadata Cache Lifetime</b> - Cache Lifetime in minutes before fresh metadata are requested from the IDP Metadata URL
|
||||
</li>
|
||||
<li>
|
||||
<b>IDP SSO Binding</b> - SAML SSO binding format to use
|
||||
</li>
|
||||
<li>
|
||||
<b>IDP Entity ID</b> - EntityID of the IdP to use. Only needed if more than one IdP is in the SAML_METADATA_URL
|
||||
<b>IDP SLO Binding</b> - SAML SLO binding format to use
|
||||
</li>
|
||||
<li>
|
||||
<b>NameID Format</b> - NameID format to request
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>ATTRIBUTES</dt>
|
||||
<dt>SP</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
<b>SP Entity ID</b> - The entity ID of your Service Provider (SP).
|
||||
</li>
|
||||
<li>
|
||||
<b>SP NameID Format</b> - NameID format to request
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Metadata Cache Duration</b> - Set the cache duration of generated metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Metadata Valid Until</b> - Set the expiration moment (in seconds) for generated metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>Sign SP Metadata</b> - Choose whether metadata produced is signed.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>SP ATTRIBUTES</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
|
@ -965,6 +1030,79 @@
|
|||
<li>
|
||||
<b>Username</b> - Attribute to use for username.
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Entity Name</b> - Contact information about your SP, to be included in the generated metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Entity Mail</b> - Contact information about your SP, to be included in the generated metadata.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>ENCRYPTION</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
The <b>Cert File</b> - <b>Cert Key</b> pair configures the path
|
||||
to certificate file and it's respective private key file.
|
||||
It is used for signing metadata, encrypting tokens and all other
|
||||
signing/encryption tasks during communication between iDP and SP.<br>
|
||||
<b>NOTE</b>: If these two parameters aren't explicitly provided, a self-signed certificate-key pair
|
||||
will be generated in "PowerDNS-Admin" root directory.<br>
|
||||
<b style="color:red;">CAUTION</b>: For production use, usage of self-signed certificates is highly discouraged.
|
||||
Use certificates from trusted CA instead.
|
||||
</li>
|
||||
<li>
|
||||
<b>Sign Authentication Request</b> - Configures if the SP should sign outgoing authentication requests.
|
||||
</li>
|
||||
<li>
|
||||
<b>Sign Logout Request & Response</b> - Configures if the SP should sign outgoing Logout requests & Logout responses.
|
||||
</li>
|
||||
<li>
|
||||
<b>Want Assertions Encrypted</b> - Choose whether the SP expects assertions received from the IDP to be encrypted.
|
||||
</li>
|
||||
<li>
|
||||
<b>Want Assertions Signed</b> - Choose whether the SP expects incoming assertions to be signed.
|
||||
</li>
|
||||
<li>
|
||||
<b>NameID Encrypted</b> - Indicates that the nameID of the logoutRequest sent by this SP will be encrypted.
|
||||
</li>
|
||||
<li>
|
||||
<b>Want NameID Encrypted</b> - Indicates a requirement for the NameID received by this SP to be encrypted.
|
||||
</li>
|
||||
<li>
|
||||
<b>Want Message Signed</b> - Choose whether the SP expects incoming messages to be signed.
|
||||
</li>
|
||||
<li>
|
||||
<b>Digest Algorithm</b> - Encryption algorithm to encode outgoing and decode incoming metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>Signature Algorithm</b> - Encryption algorithm to encode/decode signatures.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>LOGOUT</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
<b>SAML Logout</b> - Choose whether user is logged out of SAML session and possibly redirect them elsewhere.
|
||||
<ul>
|
||||
<li>
|
||||
If enabled, use SAML standard logout mechanism retreived from IDP metadata.
|
||||
</li>
|
||||
<li>
|
||||
If disabled, don't care about SAML session on logout.<br>
|
||||
Logout from PowerDNS-Admin only and keep SAML session authenticated.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<b>Logout URL</b> - Configure to redirect to a url different than PowerDNS-Admin login after a successful SAML logout.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>AUTOPROVISION</dt>
|
||||
<dd> Provision PDA user privileges based on SAML Attributes.
|
||||
<ul>
|
||||
<li>
|
||||
<b>Admin</b> - Attribute to get admin status from.<br>
|
||||
If set, look for the value 'true' to set a user as an administrator.<br>
|
||||
|
@ -978,87 +1116,9 @@
|
|||
be created and the user added to them.
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Entity ID</b> - The entity ID of your Service Provider (SP).
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Entity Name</b> - Contact information about your SP, to be included in the generated metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>SP Entity Mail</b> - Contact information about your SP, to be included in the generated metadata.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>CERTIFICATE</dt>
|
||||
<dd> Configures the path to certificate file and it's respective private key file.
|
||||
<ul>
|
||||
<li>
|
||||
The <b>Cert File</b> - <b>Cert Key</b> pair is used for signing metadata, encrypting tokens and all other signing/encryption
|
||||
tasks during communication between iDP and SP.<br>
|
||||
<b>NOTE</b>: If these two parameters aren't explicitly provided, a self-signed certificate-key pair
|
||||
will be generated in "PowerDNS-Admin" root directory.<br>
|
||||
<b style="color:red;">CAUTION</b>: For production use, usage of self-signed certificates is highly discouraged.
|
||||
Use certificates from trusted CA instead.
|
||||
</li>
|
||||
<li>
|
||||
<b>Sign Request</b> - Configures if SAML tokens should be encrypted.<br>
|
||||
If enabled a new app certificate will be generated on restart.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>LOGOUT</dt>
|
||||
<dd>
|
||||
Choose whether user is logged out of SAML session and possibly redirect them elsewhere.
|
||||
<ul>
|
||||
<li>
|
||||
<b>SAML Logout</b> - Use SAML standard logout mechanism retreived from IDP metadata.<br>
|
||||
If disabled, don't care about SAML session on logout.<br>
|
||||
Logout from PowerDNS-Admin only and keep SAML session authenticated.
|
||||
</li>
|
||||
<li>
|
||||
<b>Logout URL</b> - Configure to redirect to a url different than PowerDNS-Admin login after a successful SAML logout.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>ENCRYPTION</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
<b>Encrypted Assertion</b> - Choose whether assertions are encrypted.
|
||||
</li>
|
||||
<li>
|
||||
<b>Want Assertions Signed</b> - Expect incoming assertions to be signed.
|
||||
</li>
|
||||
<li>
|
||||
<b>Digest Algorithm</b> - Encryption algorithm to encode outgoing and decode incoming metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>Signature Algorithm</b> - Encryption algorithm to encode/decode signatures.
|
||||
</li>
|
||||
<li>
|
||||
<b>Want Message Signed</b> - Expect incoming messages to be signed.
|
||||
</li>
|
||||
<li>
|
||||
<b>Sign Metadata</b> - Choose whether metadata produced is signed.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>DURATION</dt>
|
||||
<dd> <br>
|
||||
<ul>
|
||||
<li>
|
||||
<b>Metadata Cache Duration</b> - Set the cache duration of generated metadata.
|
||||
</li>
|
||||
<li>
|
||||
<b>Metadata Valid Until</b> - Set the expiration moment (in seconds) for generated metadata.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>AUTOPROVISION</dt>
|
||||
<dd> Provision PDA user privileges based on SAML Token Attributes.
|
||||
This feature and the "Admin / Account" attribute assertion are mutually exclusive.
|
||||
<ul>
|
||||
<li>
|
||||
<b>Roles Autoprovisioning</b> - If toggled on, the PDA Role and the associations of users found in the local db, will be instantly updated from the SAML SP db every time they log in.
|
||||
<b>Roles Autoprovisioning</b> - If toggled on, the PDA Role and the associations of users found in the local db, will be instantly updated from the SAML SP db every time they log in.<br>
|
||||
<b style="color:red;">NOTE</b>:This feature and the assertion of "Admin / Account" attributes are mutually exclusive.<br>
|
||||
If used, the values for Admin/Account given above will be ignored.
|
||||
</li>
|
||||
<li>
|
||||
<b>Roles provisioning field</b> - The urn value of the attribute in the SAML Token where PDA will look for a new Role and/or new associations to domains/accounts.
|
||||
|
@ -1084,7 +1144,8 @@
|
|||
<li>
|
||||
<b>Purge Roles If Empty</b> - If toggled on, SAML logins that have no valid "powerdns-admin" records to their autoprovisioning field,
|
||||
will lose all their associations with any domain or account, also reverting to a User in the process, despite their current role in the local db.<br>
|
||||
If toggled off, in the same scenario they get to keep their existing associations and their current Role.
|
||||
If toggled off, in the same scenario they get to keep their existing associations and their current Role.<br>
|
||||
<b style="color:red;">CAUTION</b>: Enabling this feature will revoke existing users' access to their associated domains unless they have their autoprovisioning field prepopulated.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
|
|
@ -26,14 +26,15 @@
|
|||
<i class="fa fa-warning text-yellow"></i> Oops! Something went wrong
|
||||
</h3><br>
|
||||
<p>
|
||||
Login failed.<br>
|
||||
Error(s) when processing SAML Response:<br>
|
||||
Login failed.
|
||||
{% if error %}
|
||||
<br>Error(s) when processing SAML Response:<br>
|
||||
<ul>
|
||||
{% for error in errors %}
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% endif %}
|
||||
You may <a href="{{ url_for('dashboard.dashboard') }}">return to the dashboard</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue