Index: fedd/federation/authorizer.py
===================================================================
--- fedd/federation/authorizer.py	(revision 73ded037f3b219849ff05e2a1e225d7d18d266c6)
+++ fedd/federation/authorizer.py	(revision 2bc7b769d357f01cca3129c31f709f41a752f2be)
@@ -2,17 +2,19 @@
 
 from fedid import fedid
-
-class authorizer:
-    """
-    This class keeps track of authorization attributes for the various modules
-    running.  When it gets smarter it will be the basis for a real
-    attribute-based authentication system.
-    """
+from remote_service import service_caller
+from abac_remote_service import abac_service_caller
+from service_error import service_error
+
+import sys
+
+class authorizer_base:
+    """
+    Classes based on this one keep track of authorization attributes for the
+    various modules running.  This base class holds some utility functions that
+    they all potentially use.
+    """
+
     # general error exception for badly formed names.  
     class bad_name(RuntimeError): pass
-
-    def __init__(self, def_attr="testbed"):
-	self.attrs = { }
-	self.globals=set()
 
     @staticmethod
@@ -27,5 +29,6 @@
 	else: return name
 
-    def valid_name(self, name):
+    @staticmethod
+    def valid_name(name):
 	"""
 	Ensure that the given name is valid.  A valid name can either be a
@@ -42,6 +45,6 @@
 		if n: 
 		    if not (isinstance(n, basestring) or isinstance(n, fedid)):
-			raise self.bad_name("names must be either a " +\
-				"triple or a fedid")
+			raise authorizer_base.bad_name(
+				"names must be either a triple or a fedid")
 	    for n in name: 
 		if n:
@@ -49,5 +52,6 @@
 			return True
 		    else:
-			raise self.bad_name("Compound names must be " + \
+			raise authorizer_base.bad_name(
+				"Compound names must be " + \
 				"rooted in fedids: %s" % str(name))
 
@@ -56,5 +60,17 @@
 	    return True
 	else:
-	    raise self.bad_name("Names must be a triple or a fedid (%s)" % name)
+	    raise authorizer_base.bad_name(
+		    "Names must be a triple or a fedid (%s)" % name)
+
+
+class authorizer(authorizer_base):
+    """
+    This class keeps track of authorization attributes for the various modules
+    running.  When it gets smarter it will be the basis for a real
+    attribute-based authentication system.
+    """
+    def __init__(self, def_attr="testbed"):
+	self.attrs = { }
+	self.globals=set()
 
     def set_attribute(self, name, attr):
@@ -124,2 +140,98 @@
 	self.globals.discard(attr)
 
+class abac_authorizer(authorizer_base):
+    """
+    Use the ABAC authorization system to make attribute decisions.
+    """
+
+    def __init__(self, url=None, cert_file=None, cert_pwd=None,
+	    trusted_certs=None, me=None):
+	self.call_CreateContext = abac_service_caller('CreateContext')
+	self.call_CredentialUpdate = abac_service_caller('CredentialUpdate')
+	self.call_Access = abac_service_caller('Access')
+	self.globals = set()
+
+	self.url = url
+	self.cert_file = cert_file
+	self.cert_pwd = cert_pwd
+	self.trusted_certs = trusted_certs
+	self.me = me
+	self.contextID = me.get_hexstr()
+	req = { 'contextID' : self.contextID}
+	# May throw a service error
+	resp = self.call_CreateContext(self.url, req, self.cert_file,
+		self.cert_pwd, self.trusted_certs, tracefile=sys.stderr)
+
+	if resp.has_key('CreateContextResponseBody'):
+	    resp =  resp['CreateContextResponseBody']
+	    if resp.has_key('contextID'):
+		self.contextID = resp['contextID']
+	    else:
+		raise service_error(service_error.internal, 
+			"No context ID for the new authorization context")
+	else:
+	    raise service_error(service_error.internal, 
+		    "Bad response to creating service context")
+
+    def set_attribute(self, name, attr):
+	self.valid_name(name)
+	if isinstance(name, tuple):
+	    if not isinstance(name[0], fedid):
+		raise service_error(service_error.internal, 
+			"Triple not anchored in testbed")
+	    if not name[1] and not name[2]:
+		raise service_error(service_error.internal,
+			"Anonymous access not yet permitted")
+
+	    preconditions = "^".join(
+		    [ "%s.%s" % (name[0], self.auth_name(n)) \
+			    for n in name[1:3] if n ])
+
+	    req = { 
+		    'credential': [ '%s.%s<--%s' % \
+			    ( self.me, attr, preconditions) ],
+		    'context': { 'contextID': self.contextID  }
+		}
+	else:
+	    req = { 
+		    'credential': [ '%s.%s<--%s' % \
+			    ( self.me, attr, self.auth_name(name)) ],
+		    'context': { 'contextID': self.contextID }
+		}
+	print req
+	self.call_CredentialUpdate(self.url, req, self.cert_file, 
+		self.cert_pwd, self.trusted_certs, tracefile=sys.stderr)
+
+    def check_attribute(self, name, attr):
+	self.valid_name(name)
+	if attr in self.globals: return True
+
+	if isinstance(name, tuple):
+	    raise service_error(service_error.internal, 
+		    "Only fedids permitted here")
+	req = {
+		'goal': '%s:%s<<---%s' % (self.me, attr, name),
+		'context': { 'contextID': self.contextID }
+	    }
+	resp = self.call_Access(self.url, req, self.cert_file, self.cert_pwd, 
+		self.trusted_certs)
+	if resp.has_key('AccessResponseBody'):
+	    resp = resp['AccessResponseBody']
+
+	result = resp.get('result', None)
+	return (result and result.lower() == 'true')
+
+    def set_global_attribute(self, attr):
+	"""
+	Set a global attribute.  All names, even those otherwise unknown to the
+	authorizer have this attribute.
+	"""
+	self.globals.add(attr)
+
+    def unset_global_attribute(self, attr):
+	"""
+	Remove a global attribute
+	"""
+
+	self.globals.discard(attr)
+
