Do entire ACL update in a transaction, not for each machine.
[invirt/packages/invirt-web.git] / getafsgroups.py
1 #!/usr/bin/python
2 import pprint
3 import subprocess
4
5 # import ldap
6 # l = ldap.open("W92-130-LDAP-2.mit.edu")
7 # # ldap.mit.edu is 1/2 broken right now so we're going to the working backend
8 # l.simple_bind_s("", "")
9
10 # def getLdapGroups(user):
11 #     """
12 #     getLdapGroups(user): returns a generator for the list of LDAP groups containing user
13 #     """
14 #     for user_data in l.search_s("ou=affiliates,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "uid=" + user, []):
15 #         for group_data in l.search_s("ou=groups,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "uniqueMember="+user_data[0], ['cn']):
16 #             yield group_data[1]['cn'][0]
17
18 # def checkLdapGroups(user, group):
19 #     """
20 #     checkLdapGroups(user, group): returns True if and only if user is in LDAP group group
21 #     """
22 #     for result_data in l.search_s("ou=affiliates,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "uid=" + user, []):
23 #         if l.search_s("ou=groups,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "(&(cn=" + group + ")(uniqueMember="+result_data[0] + "))", []) != []:
24 #             return True
25 #     return False
26
27 class MyException(Exception):
28     pass
29
30 def getAfsGroupMembers(group, cell):
31     p = subprocess.Popen(["pts", "membership", group, '-c', cell], 
32                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
33     if p.wait():
34         return []
35     return [line.strip() for line in p.stdout.readlines()[1:]]
36
37 def checkAfsGroup(user, group, cell):
38     """
39     checkAfsGroup(user, group) returns True if and only if user is in AFS group group in cell cell
40     """
41     return user in getAfsGroupMembers(group, cell)
42
43 def getCell(locker):
44     p = subprocess.Popen(["fs", "whichcell", "/mit/" + locker], 
45                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
46     if p.wait():
47         raise MyException(p.stderr.read())
48     return p.stdout.read().split()[-1][1:-1]
49
50 def getLockerAcl(locker):
51     p = subprocess.Popen(["fs", "listacl", "/mit/" + locker], 
52                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
53     if p.wait():
54         raise MyException(p.stderr.read())
55     lines = p.stdout.readlines()
56     values = []
57     for line in lines[1:]:
58         fields = line.split()
59         if fields[0] == 'Negative':
60             break
61         if 'rlidwka' in fields[1]:
62             values.append(fields[0])
63     return values
64
65 def notLockerOwner(user, locker):
66     """
67     notLockerOwner(user, locker) returns false if and only if user administers locker.
68
69     If the user does not own the locker, returns the string reason for
70     the failure.
71     """
72     try:
73         cell = getCell(locker)
74         values = getLockerAcl(locker)
75     except MyException, e:
76         return str(e)
77
78     for entry in values:
79         if entry == user or (entry[0:6] == "system" and 
80                                 checkAfsGroup(user, entry, cell)):
81             return False
82     return "You don't have admin bits on /mit/" + locker
83
84
85 if __name__ == "__main__":
86 #    print list(getldapgroups("tabbott"))
87     print checkAfsGroup("tabbott", "system:debathena", 'athena.mit.edu')
88     print checkAfsGroup("tabbott", "system:debathena", 'sipb.mit.edu')
89     print checkAfsGroup("tabbott", "system:debathena-root", 'athena.mit.edu')
90     print checkAfsGroup("tabbott", "system:hmmt-request", 'athena.mit.edu')
91     print notLockerOwner("tabbott", "tabbott")
92     print notLockerOwner("tabbott", "debathena")
93     print notLockerOwner("tabbott", "sipb")
94     print notLockerOwner("tabbott", "lsc")
95     print notLockerOwner("tabbott", "scripts")
96     print notLockerOwner("ecprice", "hmmt")