apache_auth.py revision e0b08e6170b57f90262726eb7f04e059cb47419c
1e8819cdf80ca0e0602d22551a50f970aa68e108dmblighfrom django.contrib.auth.models import User, Group, check_password 2a5288b4bb2b09aafe914d0b7d5aab79a7e433eafshowardfrom django.contrib.auth import backends 3e8819cdf80ca0e0602d22551a50f970aa68e108dmblighfrom django.contrib import auth 4e8819cdf80ca0e0602d22551a50f970aa68e108dmblighfrom django import http 5e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 6e0b08e6170b57f90262726eb7f04e059cb47419cHsinyu Chaofrom autotest_lib.client.cros import constants 7a5288b4bb2b09aafe914d0b7d5aab79a7e433eafshowardfrom autotest_lib.frontend import thread_local 8a5288b4bb2b09aafe914d0b7d5aab79a7e433eafshowardfrom autotest_lib.frontend.afe import models, management 985f4c36b14448d8fd707b34107c7688f13f258f2Simran Basifrom autotest_lib.server import utils 10e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 11e8819cdf80ca0e0602d22551a50f970aa68e108dmblighDEBUG_USER = 'debug_user' 12e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 13a5288b4bb2b09aafe914d0b7d5aab79a7e433eafshowardclass SimpleAuthBackend(backends.ModelBackend): 140afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski """ 150afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski Automatically allows any login. This backend is for use when Apache is 160afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski doing the real authentication. Also ensures logged-in user exists in 170afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski frontend.afe.models.User database. 180afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski """ 190afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def authenticate(self, username=None, password=None): 200afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski try: 210afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user = User.objects.get(username=username) 220afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski except User.DoesNotExist: 230afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # password is meaningless 240afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user = User(username=username, 250afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski password='apache authentication') 260afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user.is_staff = True 270afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user.save() # need to save before adding groups 280afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user.groups.add(Group.objects.get( 290afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski name=management.BASIC_ADMIN)) 30e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 310afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski SimpleAuthBackend.check_afe_user(username) 320afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return user 33e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 34e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 350afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski @staticmethod 360afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def check_afe_user(username): 373dd47c247147ca6920b222d43a8eb6ee54209c8fshoward user, created = models.User.objects.get_or_create(login=username) 383dd47c247147ca6920b222d43a8eb6ee54209c8fshoward if created: 393dd47c247147ca6920b222d43a8eb6ee54209c8fshoward user.save() 40e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 410afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def get_user(self, user_id): 420afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski try: 430afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return User.objects.get(pk=user_id) 440afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski except User.DoesNotExist: 450afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return None 46e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 47e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 486f1593c98487664a6c330a638e6645dc39b4aca3showardclass GetApacheUserMiddleware(object): 490afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski """ 500afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski Middleware for use when Apache is doing authentication. Looks for 516f1593c98487664a6c330a638e6645dc39b4aca3showard REMOTE_USER in headers and passed the username found to 526f1593c98487664a6c330a638e6645dc39b4aca3showard thread_local.set_user(). If no such header is found, looks for 536f1593c98487664a6c330a638e6645dc39b4aca3showard HTTP_AUTHORIZATION header with username (this allows CLI to authenticate). 546f1593c98487664a6c330a638e6645dc39b4aca3showard If neither of those are found, DEBUG_USER is used. 550afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski """ 56e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh 570afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def process_request(self, request): 580afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # look for a username from Apache 590afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user = request.META.get('REMOTE_USER') 600afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski if user is None: 610afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # look for a user in headers. This is insecure but 620afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # it's our temporarily solution for CLI auth. 630afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski user = request.META.get('HTTP_AUTHORIZATION') 640afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski if user is None: 650afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # no user info - assume we're in development mode 6685f4c36b14448d8fd707b34107c7688f13f258f2Simran Basi user = constants.MOBLAB_USER if utils.is_moblab() else DEBUG_USER 676f1593c98487664a6c330a638e6645dc39b4aca3showard thread_local.set_user(user) 686f1593c98487664a6c330a638e6645dc39b4aca3showard 696f1593c98487664a6c330a638e6645dc39b4aca3showard 706f1593c98487664a6c330a638e6645dc39b4aca3showardclass ApacheAuthMiddleware(GetApacheUserMiddleware): 716f1593c98487664a6c330a638e6645dc39b4aca3showard """ 726f1593c98487664a6c330a638e6645dc39b4aca3showard Like GetApacheUserMiddleware, but also logs the user into Django's auth 736f1593c98487664a6c330a638e6645dc39b4aca3showard system, and replaces the username in thread_local with the actual User model 746f1593c98487664a6c330a638e6645dc39b4aca3showard object. 756f1593c98487664a6c330a638e6645dc39b4aca3showard """ 766f1593c98487664a6c330a638e6645dc39b4aca3showard 77a79583c946ce95ba0b30f5ec2de58ff13f1006d0showard 786f1593c98487664a6c330a638e6645dc39b4aca3showard def process_request(self, request): 796f1593c98487664a6c330a638e6645dc39b4aca3showard super(ApacheAuthMiddleware, self).process_request(request) 806f1593c98487664a6c330a638e6645dc39b4aca3showard username = thread_local.get_user() 81a79583c946ce95ba0b30f5ec2de58ff13f1006d0showard thread_local.set_user(None) 826f1593c98487664a6c330a638e6645dc39b4aca3showard user_object = auth.authenticate(username=username, 830afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski password='') 840afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski auth.login(request, user_object) 856f1593c98487664a6c330a638e6645dc39b4aca3showard thread_local.set_user(models.User.objects.get(login=username)) 86