1 from fnmatch import fnmatch
4 A General-purpose ACL mechanism.
6 [allow | deny] <type_of_object> <text_pattern>
\r
8 "allow all" and "deny all" are shorthand for allowing or denying all objects.
\r
9 Lines are executed from top to bottom until a match was found, typical
\r
10 iptables style. An implicit 'deny all' exists at the bottom of the list.
\r
13 allow site Max Planck Institute
\r
16 deny user scott@onlab.us
\r
20 class AccessControlList:
21 def __init__(self, aclText=None):
24 self.import_text(aclText)
26 def import_text(self, aclText):
27 # allow either newline or ';' to separate rules
28 aclText = aclText.replace("\n", ";")
29 for line in aclText.split(";"):
31 if line.startswith("#"):
39 if len(parts)==2 and (parts[1]=="all"):
40 # "allow all" has no pattern
41 parts = (parts[0], parts[1], "")
44 raise ACLValidationError(line)
46 (action, object, pattern) = parts
48 if action not in ["allow", "deny"]:
49 raise ACLValidationError(line)
51 if object not in ["site", "user", "all"]:
52 raise ACLValidationError(line)
54 self.rules.append( (action, object, pattern) )
58 for rule in self.rules:
59 lines.append( " ".join(rule) )
60 return ";\n".join(lines)
62 def test(self, user, site=None):
63 for rule in self.rules:
64 if self.match_rule(rule, user):
68 def match_rule(self, rule, user, site=None):
69 (action, object, pattern) = rule
74 if (object == "site"):
75 if fnmatch(site.name, pattern):
77 elif (object == "user"):
78 if fnmatch(user.email, pattern):
80 elif (object == "all"):
86 if __name__ == '__main__':
90 def __init__(self, siteName):
94 def __init__(self, email, siteName):
96 self.site = fakesite(siteName)
98 u_scott = fakeuser("scott@onlab.us", "ON.Lab")
99 u_bill = fakeuser("bill@onlab.us", "ON.Lab")
100 u_andy = fakeuser("acb@cs.princeton.edu", "Princeton")
101 u_john = fakeuser("jhh@cs.arizona.edu", "Arizona")
102 u_hacker = fakeuser("somehacker@foo.com", "Not A Real Site")
104 # check the "deny all" rule
105 acl = AccessControlList("deny all")
106 assert(acl.test(u_scott) == "deny")
108 # a blank ACL results in "deny all"
109 acl = AccessControlList("")
110 assert(acl.test(u_scott) == "deny")
112 # check the "allow all" rule
113 acl = AccessControlList("allow all")
114 assert(acl.test(u_scott) == "allow")
116 # allow only one site
117 acl = AccessControlList("allow site ON.Lab")
118 assert(acl.test(u_scott) == "allow")
119 assert(acl.test(u_andy) == "deny")
121 # some complicated ACL
122 acl = AccessControlList("""allow site Princeton
123 allow user *@cs.arizona.edu
125 deny user scott@onlab.us
126 allow site ON.Lab""")
128 assert(acl.test(u_scott) == "deny")
129 assert(acl.test(u_bill) == "allow")
130 assert(acl.test(u_andy) == "allow")
131 assert(acl.test(u_john) == "allow")
132 assert(acl.test(u_hacker) == "deny")