Index: fedd/federation/emulab_access.py
===================================================================
--- fedd/federation/emulab_access.py	(revision 814b5e5b5dc9a550eb5f9f31c2323ace176d7d37)
+++ fedd/federation/emulab_access.py	(revision 25f66c3f2635ccc3aa8f324905e14c8e4a67ba1b)
@@ -21,5 +21,5 @@
 from access_project import access_project
 from fedid import fedid, generate_fedid
-from authorizer import authorizer
+from authorizer import authorizer, abac_authorizer
 from service_error import service_error
 from remote_service import xmlrpc_handler, soap_handler, service_caller
@@ -105,13 +105,27 @@
         self.restricted = [ ]
         self.access = { }
-        if config.has_option("access", "accessdb"):
-            self.read_access(config.get("access", "accessdb"))
+	# XXX: this should go?
+        #if config.has_option("access", "accessdb"):
+        #    self.read_access(config.get("access", "accessdb"))
         tb = config.get('access', 'testbed')
         if tb: self.testbed = [ t.strip() for t in tb.split(',') ]
         else: self.testbed = [ ]
 
-        if config.has_option("access", "accessdb"):
-            self.read_access(config.get("access", "accessdb"), 
-		    self.make_access_project)
+	# authorization information
+	self.auth_type = config.get('access', 'auth_type') \
+		or 'legacy'
+	self.auth_dir = config.get('access', 'auth_dir')
+	accessdb = config.get("access", "accessdb")
+	# initialize the authorization system
+	if self.auth_type == 'legacy':
+	    if accessdb:
+		self.read_access(accessdb, self.make_access_project)
+	elif self.auth_type == 'abac':
+	    self.auth = abac_authorizer(load=self.auth_dir)
+	    if accessdb:
+		self.read_abac_access(accessdb, self.make_abac_access_project)
+	else:
+	    raise service_error(service_error.internal, 
+		    "Unknown auth_type: %s" % self.auth_type)
 
 	# read_state in the base_class
@@ -124,14 +138,15 @@
 	self.keys = self.state['keys']
 	self.types = self.state['types']
-	# Add the ownership attributes to the authorizer.  Note that the
-	# indices of the allocation dict are strings, but the attributes are
-	# fedids, so there is a conversion.
-	for k in self.allocation.keys():
-	    for o in self.allocation[k].get('owners', []):
-		self.auth.set_attribute(o, fedid(hexstr=k))
-	    if self.allocation[k].has_key('userconfig'):
-		sfid = self.allocation[k]['userconfig']
-		fid = fedid(hexstr=sfid)
-		self.auth.set_attribute(fid, "/%s" % sfid)
+	if self.auth_type == "legacy": 
+	    # Add the ownership attributes to the authorizer.  Note that the
+	    # indices of the allocation dict are strings, but the attributes are
+	    # fedids, so there is a conversion.
+	    for k in self.allocation.keys():
+		for o in self.allocation[k].get('owners', []):
+		    self.auth.set_attribute(o, fedid(hexstr=k))
+		if self.allocation[k].has_key('userconfig'):
+		    sfid = self.allocation[k]['userconfig']
+		    fid = fedid(hexstr=sfid)
+		    self.auth.set_attribute(fid, "/%s" % sfid)
 	self.state_lock.release()
 	self.exports = {
@@ -220,4 +235,21 @@
 	else:
 	    raise self.parse_error('Bad mapping (unbalanced parens)')
+
+    @staticmethod
+    def make_abac_access_project(str):
+	"""
+	Convert a string of the form (id, id) into an access_project.  This is
+	called by read_abac_access to convert to local attributes.  It returns
+	a tuple of the form (project, user, user) where the two users are
+	always the same.
+	"""
+
+	str = str.strip()
+	if str.startswith('(') and str.endswith(')') and str.count(',') == 1:
+	    proj, user = str.split(',')
+	    return ( proj.strip(), user.strip(), user.strip())
+	else:
+	    raise self.parse_error(
+		    'Bad mapping (unbalanced parens or more than 1 comma)')
 
 
@@ -296,4 +328,22 @@
                 [ fid ]
 
+    def lookup_abac_access(self, req, fid): 
+	# Import request credentials into this (clone later??)
+	if self.auth.import_credentials(data_list=req.get('abac_credential', [])):
+	    self.auth.save()
+
+	# Check every attribute that we know how to map and take the first
+	# success.
+	for attr in (self.access.keys()):
+	    if self.auth.check_attribute(fid, attr):
+		# XXX: needs to deal with dynamics
+		return copy.copy(self.access[attr]), (False, False, False), \
+			[ fid ]
+	    else:
+		self.log.debug("Access failed for %s %s" % (attr, fid))
+	else:
+            raise service_error(service_error.access, "Access denied")
+
+
     def do_project_allocation(self, dyn, project, user):
 	"""
@@ -433,5 +483,11 @@
 
 
-	found, dyn, owners = self.lookup_access(req, fid)
+	if self.auth_type == "legacy":
+	    found, dyn, owners = self.lookup_access(req, fid)
+	elif self.auth_type == 'abac':
+	    found, dyn, owners = self.lookup_abac_access(req, fid)
+	else:
+	    raise service_error(service_error.internal, 
+		    'Unknown auth_type: %s' % self.auth_type)
 	ap = None
 
@@ -466,4 +522,5 @@
 	for o in owners:
 	    self.auth.set_attribute(o, allocID)
+	self.auth.save()
 	try:
 	    f = open("%s/%s.pem" % (self.certdir, aid), "w")
