blob: 7fc6a0244eb16b9fef3fc837e2393cb03bf54e22 [file] [log] [blame]
Scott Baker5380c522014-06-06 14:49:43 -07001from fnmatch import fnmatch
2
3class AccessControlList:
4 def __init__(self, aclText=None):
5 self.rules = []
6 if aclText:
7 self.import_text(aclText)
8
9 def import_text(self, aclText):
10 # allow either newline or ';' to separate rules
11 aclText = aclText.replace("\n", ";")
12 for line in aclText.split(";"):
13 line = line.strip()
14 if line.startswith("#"):
15 continue
16
17 if line=="":
18 continue
19
20 parts = line.split()
21
22 if len(parts)==2 and (parts[1]=="all"):
23 # "allow all" has no pattern
24 parts = (parts[0], parts[1], "")
25
26 if len(parts)!=3:
27 raise ACLValidationError(line)
28
29 (action, object, pattern) = parts
30
31 if action not in ["allow", "deny"]:
32 raise ACLValidationError(line)
33
34 if object not in ["site", "user", "all"]:
35 raise ACLValidationError(line)
36
37 self.rules.append( (action, object, pattern) )
38
39 def __str__(self):
40 lines = []
41 for rule in self.rules:
42 lines.append( " ".join(rule) )
43 return ";\n".join(lines)
44
45 def test(self, user):
46 for rule in self.rules:
47 if self.match_rule(rule, user):
48 return rule[0]
49 return "deny"
50
51 def match_rule(self, rule, user):
52 (action, object, pattern) = rule
53
54 if (object == "site"):
55 if fnmatch(user.site.name, pattern):
56 return True
57 elif (object == "user"):
58 if fnmatch(user.email, pattern):
59 return True
60 elif (object == "all"):
61 return True
62
63 return False
64
65
66if __name__ == '__main__':
67 class fakesite:
68 def __init__(self, siteName):
69 self.name = siteName
70
71 class fakeuser:
72 def __init__(self, email, siteName):
73 self.email = email
74 self.site = fakesite(siteName)
75
76 u_scott = fakeuser("scott@onlab.us", "ON.Lab")
77 u_bill = fakeuser("bill@onlab.us", "ON.Lab")
78 u_andy = fakeuser("acb@cs.princeton.edu", "Princeton")
79 u_john = fakeuser("jhh@cs.arizona.edu", "Arizona")
80 u_hacker = fakeuser("somehacker@foo.com", "Not A Real Site")
81
82 # check the "deny all" rule
83 acl = AccessControlList("deny all")
84 assert(acl.test(u_scott) == "deny")
85
86 # a blank ACL results in "deny all"
87 acl = AccessControlList("")
88 assert(acl.test(u_scott) == "deny")
89
90 # check the "allow all" rule
91 acl = AccessControlList("allow all")
92 assert(acl.test(u_scott) == "allow")
93
94 # allow only one site
95 acl = AccessControlList("allow site ON.Lab")
96 assert(acl.test(u_scott) == "allow")
97 assert(acl.test(u_andy) == "deny")
98
99 # some complicated ACL
100 acl = AccessControlList("""allow site Princeton
101 allow user *@cs.arizona.edu
102 deny site Arizona
103 deny user scott@onlab.us
104 allow site ON.Lab""")
105
106 assert(acl.test(u_scott) == "deny")
107 assert(acl.test(u_bill) == "allow")
108 assert(acl.test(u_andy) == "allow")
109 assert(acl.test(u_john) == "allow")
110 assert(acl.test(u_hacker) == "deny")
111
112 print acl
113