source: asadb/util/sync_moira_authz.py @ 8cb8a9c

space-accessstablestage
Last change on this file since 8cb8a9c was 8cb8a9c, checked in by Alex Dehnert <adehnert@…>, 14 years ago

Put in the right lists to sync

  • Property mode set to 100755
File size: 5.1 KB
Line 
1#!/usr/bin/python
2
3import afs.pts
4import ldap
5import ldap.dn
6import ldap.filter
7import os
8import sys
9import subprocess
10
11if __name__ == '__main__':
12    cur_file = os.path.abspath(__file__)
13    django_dir = os.path.abspath(os.path.join(os.path.dirname(cur_file), '..'))
14    sys.path.append(django_dir)
15    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
16
17import django.contrib.auth.models
18
19import mit
20import settings
21
22class DjangoConnector(object):
23    def __init__(self, ):
24        self.dj_groups = django.contrib.auth.models.Group.objects
25
26    def sync_members(self, sys_name, dj_name, ):
27        kept = []
28        added = []
29        nonexist = []
30        created = []
31        removed = []
32        sys_members = self.get_members(sys_name)
33        dj_group = self.dj_groups.get(name=dj_name)
34        dj_members = dj_group.user_set.all()
35        dj_usernames = set([m.username for m in dj_members])
36        for username in sys_members:
37            if username in dj_usernames:
38                kept.append(username)
39            else:
40                # Need to add to the Django group
41                try:
42                    user, is_new = mit.get_or_create_mit_user(username, )
43                    if is_new: created.append(username)
44                    user.groups.add(dj_group)
45                    added.append(username)
46                except ValueError:
47                    nonexist.append(username)
48        for user in dj_members:
49            username = user.username
50            if username in sys_members:
51                assert username in kept
52            else:
53                user.groups.remove(dj_group)
54                removed.append(username)
55        return {
56            'change' : len(added) + len(removed),
57            'keep' : kept,
58            'add'  : added,
59            'create' : created,
60            'nonexist' : nonexist,
61            'remove': removed,
62        }
63
64    def sync_many(con, what, force_print=False, ):
65        changed = False
66        results = {}
67        for sys_name, dj_group in what:
68            assert dj_group not in results
69            results[dj_group] = con_afs.sync_members(sys_name, dj_group)
70            if results[dj_group]['change']: changed = True
71        if changed or force_print:
72            for group in results:
73                print ""
74                print "Results for %s:" % (group, )
75                for key, value in results[group].items():
76                    print "%7s:\t%s" % (key, value, )
77
78
79class LDAPConnector(DjangoConnector):
80    name = "LDAP"
81
82    def __init__(self, *args, **kwargs):
83        super(LDAPConnector, self).__init__(*args, **kwargs)
84        self.con = ldap.initialize('ldaps://ldap-too.mit.edu')
85        self.con.simple_bind_s("", "")
86
87    def get_members(self, groupname):
88        base_dn = 'ou=lists,ou=moira,dc=mit,dc=edu'
89        groupfilter = ldap.filter.filter_format('(&(objectClass=group)(displayName=%s))', [groupname])
90        result = self.con.search_s(base_dn, ldap.SCOPE_SUBTREE, groupfilter, )
91        if len(result) > 1: print "WARNING: More than one result returned for %s" % groupname
92        if len(result) < 1: print "WARNING: Only no results returned for %s" % groupname
93        attrs = result[0][1]
94        members = attrs['member']
95        ret = set()
96        for member in members:
97            member_dn = ldap.dn.explode_dn(member)
98            assert len(member_dn) == 5
99            c_val, c_type, c_moira, c_mit, c_edu = member_dn
100            assert (c_moira, c_mit, c_edu, ) == ('OU=moira', 'dc=MIT', 'dc=EDU', )
101            c_val_key, c_val_sep, c_val_val = c_val.partition('=')
102            if c_type == 'OU=strings':
103                ret.add(('string', c_val_val, ))
104            elif c_type == 'OU=users':
105                ret.add(('user', c_val_val, ))
106            elif c_type == 'OU=kerberos':
107                ret.add(('kerberos', c_val_val, ))
108            else:
109                assert False, "Don't know what %s is" % (c_type, )
110        return [r[1] for r in ret if r[0] == 'user']
111
112class AFSConnector(DjangoConnector):
113    name = "AFS"
114
115    def __init__(self, *args, **kwargs):
116        super(AFSConnector, self).__init__(*args, **kwargs)
117        self.login()
118        self.pts = afs.pts.PTS(sec=afs.pts.PTS_ENCRYPT, cell='athena.mit.edu', )
119    def login(self, ):
120        if settings.KRB_KEYTAB:
121            kinit_cmd = ['kinit', '-k', '-t', settings.KRB_KEYTAB, settings.KRB_PRINCIPAL, ]
122            subprocess.check_call(kinit_cmd)
123            subprocess.check_call(['aklog', 'athena', ])
124
125    def get_members(self, groupname, ):
126        afs_members = self.pts.getEntry("system:%s" % (groupname, )).members
127        members = [ m.name for m in afs_members ]
128        return members
129
130sync_pairs = [
131    ('asa-admin', 'asa-ebm', ),
132    ('asa-db-mit-deskworker', 'mit-deskworker', ),
133    ('asa-db-mit-offices', 'mit-offices', ),
134    ('asa-db-mit-sao', 'mit-sao', ),
135]
136
137def test_memberships(cons):
138    for sys_name, dj_group in sync_pairs:
139        for con in cons:
140            members = con.get_members(sys_name)
141            print "%s\t%s\t%s" % (con.name, sys_name, sorted(members))
142
143if __name__ == '__main__':
144    con_afs = AFSConnector()
145    #con_ldap = LDAPConnector()
146    #test_memberships([con_afs, con_ldap, ])
147    con_afs.sync_many(sync_pairs)
Note: See TracBrowser for help on using the repository browser.