from fnmatch import fnmatch class AccessControlList: def __init__(self, aclText=None): self.rules = [] if aclText: self.import_text(aclText) def import_text(self, aclText): # allow either newline or ';' to separate rules aclText = aclText.replace("\n", ";") for line in aclText.split(";"): line = line.strip() if line.startswith("#"): continue if line=="": continue parts = line.split() if len(parts)==2 and (parts[1]=="all"): # "allow all" has no pattern parts = (parts[0], parts[1], "") if len(parts)!=3: raise ACLValidationError(line) (action, object, pattern) = parts if action not in ["allow", "deny"]: raise ACLValidationError(line) if object not in ["site", "user", "all"]: raise ACLValidationError(line) self.rules.append( (action, object, pattern) ) def __str__(self): lines = [] for rule in self.rules: lines.append( " ".join(rule) ) return ";\n".join(lines) def test(self, user): for rule in self.rules: if self.match_rule(rule, user): return rule[0] return "deny" def match_rule(self, rule, user): (action, object, pattern) = rule if (object == "site"): if fnmatch(user.site.name, pattern): return True elif (object == "user"): if fnmatch(user.email, pattern): return True elif (object == "all"): return True return False if __name__ == '__main__': class fakesite: def __init__(self, siteName): self.name = siteName class fakeuser: def __init__(self, email, siteName): self.email = email self.site = fakesite(siteName) u_scott = fakeuser("scott@onlab.us", "ON.Lab") u_bill = fakeuser("bill@onlab.us", "ON.Lab") u_andy = fakeuser("acb@cs.princeton.edu", "Princeton") u_john = fakeuser("jhh@cs.arizona.edu", "Arizona") u_hacker = fakeuser("somehacker@foo.com", "Not A Real Site") # check the "deny all" rule acl = AccessControlList("deny all") assert(acl.test(u_scott) == "deny") # a blank ACL results in "deny all" acl = AccessControlList("") assert(acl.test(u_scott) == "deny") # check the "allow all" rule acl = AccessControlList("allow all") assert(acl.test(u_scott) == "allow") # allow only one site acl = AccessControlList("allow site ON.Lab") assert(acl.test(u_scott) == "allow") assert(acl.test(u_andy) == "deny") # some complicated ACL acl = AccessControlList("""allow site Princeton allow user *@cs.arizona.edu deny site Arizona deny user scott@onlab.us allow site ON.Lab""") assert(acl.test(u_scott) == "deny") assert(acl.test(u_bill) == "allow") assert(acl.test(u_andy) == "allow") assert(acl.test(u_john) == "allow") assert(acl.test(u_hacker) == "deny") print acl