Take advantage of the newly added symbolic names for PTS connection
[invirt/packages/invirt-base.git] / python / invirt / authz / locker.py
index 4e22d2a..7982f8d 100644 (file)
@@ -4,16 +4,17 @@ from afs import acl
 from afs import fs
 from afs import pts
 
+from invirt import common
 from invirt.config import structs as config
+from invirt import remctl
+
 
 #
 # expandOwner and expandAdmin form the API that needs to be exported
 # for all authz modules.
 #
 
-# TODO: Make expandOwner and expandAdmin deal with acquiring tokens
-# and encrypting the connection to the prdb as necessary/requested by
-# the configuration.
+
 def expandOwner(name):
     """Expand an owner to a list of authorized users.
 
@@ -28,15 +29,16 @@ def expandOwner(name):
     try:
         path = _lockerPath(name)
         cell = fs.whichcell(path)
+        auth = _authenticate(cell)
         a = acl.ACL.retrieve(path)
 
         allowed = set()
         for ent in a.pos:
             if a.pos[ent] & acl.ADMINISTER:
-                allowed.update(_expandGroup(ent, cell))
+                allowed.update(_expandGroup(ent, cell=cell, auth=auth))
         for ent in a.neg:
             if a.neg[ent] & acl.ADMINISTER:
-                allowed.difference_update(_expandGroup(ent, cell))
+                allowed.difference_update(_expandGroup(ent, cell=cell, auth=auth))
 
         return allowed
     except OSError, e:
@@ -56,14 +58,42 @@ def expandAdmin(name, owner):
     administrator is always interpreted as an AFS entry (either a user
     or a group) in the home cell (athena.mit.edu for XVM).
     """
-    return _expandGroup(name)
+    cell = config.authz.cells[0].cell
+    auth = _authenticate(cell)
+    return _expandGroup(name, cell=cell, auth=auth)
 
 
 #
 # These are helper functions, and aren't part of the authz API
 #
 
-def _expandGroup(name, cell=None):
+
+def _authenticate(cell):
+    """Acquire AFS tokens for a cell if encryption is required by config.
+
+    If the Invirt configuration requires connections to this cell to
+    be encrypted, acquires tokens and returns True. Otherwise, returns
+    False. Consumers of this function must still be sure to encrypt
+    their own connections if necessary.
+
+    Cells not listed in the Invirt configuration default to requiring
+    encryption in order to maintain security by default.
+
+    Due to AFS's cross-realm auto-PTS-creation mechanism, using
+    authenticated connections by default should only fail for cells
+    which authenticate directly against the machine's home realm and
+    cells distantly related to the machine's home realm.
+    """
+    for c in config.authz.cells:
+        if c.cell == cell and not c.auth:
+            return False
+
+    remctl.checkKinit()
+    common.captureOutput(['aklog', '-c', cell])
+    return True
+
+
+def _expandGroup(name, cell=None, auth=False):
     """Expand an AFS group into a list of its members.
 
     Because groups are not global, but can vary from cell to cell,
@@ -80,7 +110,8 @@ def _expandGroup(name, cell=None):
     to retrieve its membership, we assume it's empty.
     """
     try:
-        ent = pts.PTS(cell).getEntry(name)
+        ent = pts.PTS(cell, pts.PTS_ENCRYPT if auth else pts.PTS_UNAUTH).\
+            getEntry(name)
         if ent.id > 0:
             return set([ent.name])
         else: