mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 01:47:35 -02:30
Fix up some SAML issues
* Fix an issue I created overriding authenticate * Fix up attribute mapping using an identity provider class. The methods built into django-social-auth for saml are probably not going to work. We also now expose those mappings in a settings attrs map that the user can override.
This commit is contained in:
@@ -18,6 +18,7 @@ from radiusauth.backends import RADIUSBackend as BaseRADIUSBackend
|
|||||||
|
|
||||||
# social
|
# social
|
||||||
from social.backends.saml import SAMLAuth as BaseSAMLAuth
|
from social.backends.saml import SAMLAuth as BaseSAMLAuth
|
||||||
|
from social.backends.saml import SAMLIdentityProvider as BaseSAMLIdentityProvider
|
||||||
|
|
||||||
# Ansible Tower
|
# Ansible Tower
|
||||||
from awx.api.license import feature_enabled
|
from awx.api.license import feature_enabled
|
||||||
@@ -100,13 +101,38 @@ class RADIUSBackend(BaseRADIUSBackend):
|
|||||||
return None
|
return None
|
||||||
return super(RADIUSBackend, self).get_user(user_id)
|
return super(RADIUSBackend, self).get_user(user_id)
|
||||||
|
|
||||||
|
class TowerSAMLIdentityProvider(BaseSAMLIdentityProvider):
|
||||||
|
'''
|
||||||
|
Custom Identity Provider to make attributes to what we expect
|
||||||
|
'''
|
||||||
|
|
||||||
|
def get_user_permanent_id(self, attributes):
|
||||||
|
return attributes[django_settings.SOCIAL_AUTH_SAML_ATTRS_PERMANENT_ID]
|
||||||
|
|
||||||
|
def get_user_details(self, attributes):
|
||||||
|
"""
|
||||||
|
Given the SAML attributes extracted from the SSO response, get
|
||||||
|
the user data like name.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
attrs = dict()
|
||||||
|
for social_attr in django_settings.SOCIAL_AUTH_SAML_ATTRS_MAP:
|
||||||
|
map_attr = django_settings.SOCIAL_AUTH_SAML_ATTRS_MAP[social_attr]
|
||||||
|
attrs[social_attr] = unicode(attributes[map_attr][0]) if map_attr in attributes else None
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class SAMLAuth(BaseSAMLAuth):
|
class SAMLAuth(BaseSAMLAuth):
|
||||||
'''
|
'''
|
||||||
Custom SAMLAuth backend to verify license status
|
Custom SAMLAuth backend to verify license status
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def authenticate(self, username, password):
|
def get_idp(self, idp_name):
|
||||||
|
"""Given the name of an IdP, get a SAMLIdentityProvider instance"""
|
||||||
|
idp_config = self.setting('ENABLED_IDPS')[idp_name]
|
||||||
|
return TowerSAMLIdentityProvider(idp_name, **idp_config)
|
||||||
|
|
||||||
|
def authenticate(self, *args, **kwargs):
|
||||||
if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
|
if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
|
||||||
django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, django_settings.SOCIAL_AUTH_SAML_ORG_INFO,
|
django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, django_settings.SOCIAL_AUTH_SAML_ORG_INFO,
|
||||||
django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
|
django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
|
||||||
@@ -115,7 +141,7 @@ class SAMLAuth(BaseSAMLAuth):
|
|||||||
if not feature_enabled('enterprise_auth'):
|
if not feature_enabled('enterprise_auth'):
|
||||||
logger.error("Unable to authenticate, license does not support SAML authentication")
|
logger.error("Unable to authenticate, license does not support SAML authentication")
|
||||||
return None
|
return None
|
||||||
return super(SAMLAuth, self).authenticate(username, password)
|
return super(SAMLAuth, self).authenticate(*args, **kwargs)
|
||||||
|
|
||||||
def get_user(self, user_id):
|
def get_user(self, user_id):
|
||||||
if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
|
if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
|
||||||
|
|||||||
@@ -387,6 +387,14 @@ SOCIAL_AUTH_SAML_TECHNICAL_CONTACT = {}
|
|||||||
SOCIAL_AUTH_SAML_SUPPORT_CONTACT = {}
|
SOCIAL_AUTH_SAML_SUPPORT_CONTACT = {}
|
||||||
SOCIAL_AUTH_SAML_ENABLED_IDPS = {}
|
SOCIAL_AUTH_SAML_ENABLED_IDPS = {}
|
||||||
|
|
||||||
|
SOCIAL_AUTH_SAML_ATTRS_PERMANENT_ID = "name_id"
|
||||||
|
SOCIAL_AUTH_SAML_ATTRS_MAP = {
|
||||||
|
"first_name": "User.FirstName",
|
||||||
|
"last_name": "User.LastName",
|
||||||
|
"username": "User.email",
|
||||||
|
"email": "User.email",
|
||||||
|
}
|
||||||
|
|
||||||
SOCIAL_AUTH_LOGIN_URL = '/'
|
SOCIAL_AUTH_LOGIN_URL = '/'
|
||||||
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/sso/complete/'
|
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/sso/complete/'
|
||||||
SOCIAL_AUTH_LOGIN_ERROR_URL = '/sso/error/'
|
SOCIAL_AUTH_LOGIN_ERROR_URL = '/sso/error/'
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ from awx.main.models import AuthToken
|
|||||||
class SocialAuthMiddleware(SocialAuthExceptionMiddleware):
|
class SocialAuthMiddleware(SocialAuthExceptionMiddleware):
|
||||||
|
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
request.META['SERVER_PORT'] = 80 # FIXME
|
|
||||||
|
|
||||||
token_key = request.COOKIES.get('token', '')
|
token_key = request.COOKIES.get('token', '')
|
||||||
token_key = urllib.quote(urllib.unquote(token_key).strip('"'))
|
token_key = urllib.quote(urllib.unquote(token_key).strip('"'))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user