acl support for deployments
diff --git a/planetstack/core/acl.py b/planetstack/core/acl.py
new file mode 100644
index 0000000..7fc6a02
--- /dev/null
+++ b/planetstack/core/acl.py
@@ -0,0 +1,113 @@
+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
+