+++ /dev/null
-import errno
-
-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.
-#
-
-
-def expandOwner(name):
- """Expand an owner to a list of authorized users.
-
- For the locker authz module, an owner is an Athena locker. Those
- users who have been given the administrator ('a') bit on the root
- of a locker are given access to any VM owned by that locker,
- unless they also have been given a negative administrator bit.
-
- If a locker doesn't exist, or we can't access the permissions, we
- assume the ACL is empty.
- """
- 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=cell, auth=auth))
- for ent in a.neg:
- if a.neg[ent] & acl.ADMINISTER:
- allowed.difference_update(_expandGroup(ent, cell=cell, auth=auth))
-
- return allowed
- except OSError, e:
- if e.errno in (errno.ENOENT, errno.EACCES):
- return []
- else:
- raise
-
-
-def expandAdmin(name, owner):
- """Expand an administrator to a list of authorized users.
-
- Because the interpretation of an administrator might depend on the
- owner, the owner is passed in as an argument.
-
- However, in the case of locker-based authentication, the
- administrator is always interpreted as an AFS entry (either a user
- or a group) in the home cell (athena.mit.edu for XVM).
- """
- cell = config.authz.afs.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 _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.afs.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,
- this function accepts as an optional argument the cell in which
- this group should be resolved.
-
- If no cell is specified, it is assumed that the default cell (or
- ThisCell) should be used.
-
- If the name is a user, not a group, then a single-element set with
- the same name is returned.
-
- As with expandOwner, if a group doesn't exist or if we're unable
- to retrieve its membership, we assume it's empty.
- """
- try:
- ent = pts.PTS(cell, pts.PTS_ENCRYPT if auth else pts.PTS_UNAUTH).\
- getEntry(name)
- if ent.id > 0:
- return set([ent.name])
- else:
- return set([x.name for x in ent.members])
- except OSError, e:
- if e.errno in (errno.ENOENT, errno.EACCESS):
- return set()
- else:
- raise
-
-
-def _lockerPath(owner):
- """Given the name of a locker, return a path to that locker.
-
- This turns out to be pretty simple, thanks to the /mit
- automounter.
- """
- return '/mit/%s' % owner