]> sipb.mit.edu Git - snippets/.git/blob - __init__.py
Wrappers for safely calling commands in a new PAG
[snippets/.git] / __init__.py
1 import os
2 import subprocess
3 import ldap
4 import ldap.filter
5
6 from django.contrib.auth.middleware import RemoteUserMiddleware
7 from django.contrib.auth.backends import RemoteUserBackend
8 from django.contrib.auth.views import login
9 from django.contrib.auth import REDIRECT_FIELD_NAME
10 from django.http import HttpResponseRedirect
11 from django.contrib import auth
12 from django.core.exceptions import ObjectDoesNotExist
13 from django.core.validators import URLValidator, ValidationError
14
15 import settings
16
17 def zephyr(msg, clas='message', instance='log', rcpt='nobody',):
18     proc = subprocess.Popen(
19         ['zwrite', '-d', '-n', '-c', clas, '-i', instance, rcpt, ],
20         stdin=subprocess.PIPE, stdout=subprocess.PIPE
21     )
22     proc.communicate(msg)
23
24 def UrlOrAfsValidator(value):
25     if value.startswith('/mit/') or value.startswith('/afs/'):
26         return
27     else:
28         try:
29             URLValidator()(value)
30         except ValidationError:
31             raise ValidationError('Provide a valid URL or AFS path')
32
33 def pag_check_helper(fn, args, aklog=False, ccname=None, **kwargs):
34     if 'executable' in kwargs:
35         raise ValueError('"executable" not supported with pag_check_*')
36
37     env = None
38     if 'env' in kwargs:
39         env = kwargs['env']
40         del kwargs['env']
41     if ccname:
42         if env is not None:
43             env = dict(env)
44         else:
45             env = dict(os.environ)
46         env['KRB5CCNAME'] = ccname
47
48     pagsh_cmd = 'exec "$@"'
49     if aklog: pagsh_cmd = "aklog && " + pagsh_cmd
50     args = ['pagsh', '-c', pagsh_cmd, 'exec', ] + args
51
52     return fn(args, env=env, **kwargs)
53
54 def pag_check_call(args, **kwargs):
55     return pag_check_helper(subprocess.check_call, args, **kwargs)
56 def pag_check_output(args, **kwargs):
57     return pag_check_helper(subprocess.check_output, args, **kwargs)
58
59 class ScriptsRemoteUserMiddleware(RemoteUserMiddleware):
60     header = 'SSL_CLIENT_S_DN_Email'
61
62 class ScriptsRemoteUserBackend(RemoteUserBackend):
63     def clean_username(self, username, ):
64         if '@' in username:
65             name, domain = username.split('@')
66             assert domain.upper() == 'MIT.EDU'
67             return name
68         else:
69             return username
70     def configure_user(self, user, ):
71         username = user.username
72         user.password = "ScriptsSSLAuth"
73         con = ldap.open('ldap-too.mit.edu')
74         con.simple_bind_s("", "")
75         dn = "dc=mit,dc=edu"
76         fields = ['cn', 'sn', 'givenName', 'mail', ]
77         userfilter = ldap.filter.filter_format('uid=%s', [username])
78         result = con.search_s('dc=mit,dc=edu', ldap.SCOPE_SUBTREE, userfilter, fields)
79         if len(result) == 1:
80             user.first_name = result[0][1]['givenName'][0]
81             user.last_name = result[0][1]['sn'][0]
82             try:
83                 user.email = result[0][1]['mail'][0]
84             except KeyError:
85                 user.email = username + '@mit.edu'
86             try:
87                 user.groups.add(auth.models.Group.objects.get(name='mit'))
88             except ObjectDoesNotExist:
89                 print "Failed to retrieve mit group"
90         else:
91             raise ValueError, ("Could not find user with username '%s' (filter '%s')"%(username, userfilter))
92         try:
93             user.groups.add(auth.models.Group.objects.get(name='autocreated'))
94         except ObjectDoesNotExist:
95             print "Failed to retrieve autocreated group"
96         user.save()
97         return user
98
99 def get_or_create_mit_user(username, ):
100     """
101     Given an MIT username, return a Django user object for them.
102     If necessary, create (and save) the Django user for them.
103     If the MIT user doesn't exist, raises ValueError.
104     """
105     user, created = auth.models.User.objects.get_or_create(username=username, )
106     if created:
107         backend = ScriptsRemoteUserBackend()
108         # Raises ValueError if the user doesn't exist
109         try:
110             return backend.configure_user(user), created
111         except ValueError:
112             user.delete()
113             raise
114     else:
115         return user, created
116
117 def scripts_login(request, **kwargs):
118     host = request.META['HTTP_HOST'].split(':')[0]
119     if host == 'localhost':
120         return login(request, **kwargs)
121     elif request.META['SERVER_PORT'] == '444':
122         if request.user.is_authenticated():
123             # They're already authenticated --- go ahead and redirect
124             if 'redirect_field_name' in kwargs:
125                 redirect_field_name = kwargs['redirect_field_names']
126             else:
127                 from django.contrib.auth import REDIRECT_FIELD_NAME
128                 redirect_field_name = REDIRECT_FIELD_NAME
129             redirect_to = request.REQUEST.get(redirect_field_name, '')
130             if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
131                 redirect_to = settings.LOGIN_REDIRECT_URL
132             return HttpResponseRedirect(redirect_to)
133         else:
134             return login(request, **kwargs)
135     else:
136         # Move to port 444
137         redirect_to = "https://%s:444%s" % (host, request.META['REQUEST_URI'], )
138         return HttpResponseRedirect(redirect_to)