Changeset 3bf0b3c


Ignore:
Timestamp:
Sep 22, 2010 1:36:57 PM (14 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master
Children:
1fc09db
Parents:
5d854e1
Message:

Looks like this works pretty well in testing now, including setting attributes.

Thread safety added.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/federation/authorizer.py

    r5d854e1 r3bf0b3c  
    11#/usr/local/bin/python
    22
     3from string import join
    34from tempfile import mkstemp
    45from subprocess import call
     6from threading import Lock
     7
    58from fedid import fedid
    69from remote_service import service_caller
     
    811from service_error import service_error
    912
     13
    1014import ABAC
    1115import pickle
     
    1317import sys
    1418import os
     19import re
    1520
    1621class authorizer_base:
     
    178183    """
    179184
    180     def __init__(self, certs=None, me=None, key=None, from_dir=None):
     185    def __init__(self, certs=None, me=None, key=None):
    181186        self.bad_name = authorizer_base.bad_name
    182187        self.attribute_error = authorizer_base.attribute_error
     
    184189        self.creddy = '/usr/local/bin/creddy'
    185190        self.me = me
    186         self.my_key = key
     191        self.key = key
    187192        self.context = ABAC.Context()
     193        self.lock = Lock()
     194
     195        if me:
     196            self.fedid = fedid(file=self.me)
     197            self.context.load_id_file(self.me)
     198
    188199        for dir in certs or []:
    189200            self.context.load_directory(dir)
     
    199210                    # create temp file
    200211                    f, fn = mkstemp()
    201                     f.close()
     212                    os.close(f)
    202213                except EnvironmentError, e:
    203214                    raise self.attribute_error(
     
    205216
    206217                # Create the attribute certificate with creddy
    207                 rv = call([creddy, '--attribute', '--issuer=%s' % self.me,
     218                cmd = [self.creddy, '--attribute', '--issuer=%s' % self.me,
    208219                    '--key=%s' % self.key, '--role=%s' % attr,
    209                     '--subject-id=%s' % name, '--out=%s' % fn])
     220                    '--subject-id=%s' % name, '--out=%s' % fn]
     221                rv = call(cmd)
    210222                if rv == 0:
     223                    self.lock.acquire()
    211224                    # load it to context and remove the file
    212                     self.context.load_attribute(fn)
     225                    rv = self.context.load_attribute_file(fn)
     226                    self.lock.release()
    213227                    os.unlink(fn)
    214228                else:
     
    220234        elif cert:
    221235            # Insert this credential into the context
     236            self.lock.acquire()
    222237            self.context.load_attribute_chunk(cert)
     238            self.lock.release()
    223239        else:
    224240            raise self.attribute_error("Neither name/attr nor cert is set")
     
    229245            raise self.bad_name("ABAC doesn't understand three-names")
    230246        else:
    231             proof, rv = self.context.query(attr, name)
     247           
     248            # Naked attributes are attested by this principal
     249            if attr.find('.') == -1: a = "%s.%s" % (self.fedid, attr)
     250            else: a = attr
     251
     252            self.lock.acquire()
     253            proof, rv = self.context.query(a, name)
    232254            # XXX delete soon
    233             if not rv and attr in self.globals: return True
    234             else: return rv
     255            if not rv and attr in self.globals: rv = True
     256            self.lock.release()
     257
     258            return rv
    235259
    236260    def set_global_attribute(self, attr):
     
    239263        authorizer have this attribute.
    240264        """
     265        self.lock.acquire()
    241266        self.globals.add(attr)
     267        self.lock.release()
    242268
    243269    def unset_global_attribute(self, attr):
     
    246272        """
    247273
     274        self.lock.acquire()
    248275        self.globals.discard(attr)
     276        self.lock.release()
    249277
    250278    def clone(self):
     279        self.lock.acquire()
    251280        rv = abac_authorizer(me=self.me, key=self.key)
    252281        rv.globals = self.globals.copy()
    253282        rv.context = ABAC.Context(self.context)
     283        self.lock.release()
    254284        return rv
    255285
    256286    def save(self, dir):
    257         os.mkdir(dir)
    258 
    259         f = open("%s/globals" % dir, "w")
    260         pickle.dump(self.globals, f)
    261         f.close()
    262 
    263         if self.me and self.key:
    264             f = open("%s/me" % dir, "w")
    265             pickle.dump(self.me, f)
     287        self.lock.acquire()
     288        try:
     289            if not os.access(dir, os.F_OK):
     290                os.mkdir(dir)
     291
     292            f = open("%s/globals" % dir, "w")
     293            pickle.dump(self.globals, f)
    266294            f.close()
    267             f = open("%s/key" % dir, "w")
    268             pickle.dump(self.key, f)
     295
     296            if self.me and self.key:
     297                f = open("%s/me" % dir, "w")
     298                pickle.dump(self.me, f)
     299                f.close()
     300                f = open("%s/key" % dir, "w")
     301                pickle.dump(self.key, f)
     302                f.close()
     303            if not os.access("%s/certs" %dir, os.F_OK):
     304                os.mkdir("%s/certs" % dir)
     305            seenit = set()
     306            #remove old certs
     307            for fn in [ f for f in os.listdir("%s/certs" % dir) \
     308                    if re.match('.*\.der$', f)]:
     309                os.unlink('%s/certs/%s' % (dir, fn))
     310            ii = 0
     311            ai = 0
     312            for c in self.context.credentials():
     313                id = c.issuer_cert()
     314                attr = c.attribute_cert()
     315                # NB: file naming conventions matter here.  The trailing_ID and
     316                # _attr are required by ABAC.COntext.load_directory()
     317                if id not in seenit:
     318                    f = open("%s/certs/ID_%03d_ID.der" % (dir, ii), "w")
     319                    print >>f, id
     320                    f.close()
     321                    ii += 1
     322                    seenit.add(id)
     323                if attr:
     324                    f = open("%s/certs/attr_%03d_attr.der" % (dir, ai), "w")
     325                    print >>f, attr
     326                    f.close()
     327                    ai += 1
     328        except EnvironmentError, e:
     329            self.lock.release()
     330            raise e
     331        except pickle.PickleError, e:
     332            self.lock.release()
     333            raise e
     334        self.lock.release()
     335
     336    def load(self, dir):
     337        self.lock.acquire()
     338        try:
     339            if os.access("%s/me" % dir, os.R_OK):
     340                f = open("%s/me" % dir, "r")
     341                self.me = pickle.load(f)
     342                f.close()
     343                if self.me:
     344                    self.fedid = fedid(file=self.me)
     345            else:
     346                self.me = None
     347            if os.access("%s/key" % dir, os.R_OK):
     348                f = open("%s/key" % dir, "r")
     349                self.key = pickle.load(f)
     350                f.close()
     351            else:
     352                self.key = None
     353            f = open("%s/globals" % dir, "r")
     354            self.globals = pickle.load(f)
    269355            f.close()
    270         os.mkdir("%s/certs" % dir)
    271         seenit = set()
    272         ii = 0
    273         ai = 0
     356            self.context = ABAC.Context()
     357            self.context.load_directory("%s/certs" % dir)
     358        except EnvironmentError, e:
     359            self.lock.release()
     360            raise e
     361        except pickle.PickleError, e:
     362            self.lock.release()
     363            raise e
     364        self.lock.release()
     365
     366    def __str__(self):
     367        def encode_role(r):
     368            if r.is_principal():
     369                return "%s" % r.principal()
     370            elif r.is_role():
     371                return "%s.%s" % (r.principal(), r.role_name())
     372            elif r.is_linking():
     373                return "%s.%s.%s" % \
     374                        (r.principal(), r.linking_role(), r.role_name())
     375
     376        self.lock.acquire()
     377        rv = "%s" % self.fedid
    274378        for c in self.context.credentials():
    275             id = c.issuer_cert()
    276             attr = c.attribute_cert()
    277             if id not in seenit:
    278                 f = open("%s/certs/%03d_ID.der" % (dir, ii), "w")
    279                 print >>f, id
    280                 f.close()
    281                 ii += 1
    282                 seenit.add(id)
    283             if attr:
    284                 f = open("%s/certs/%03d_attr.der" % (dir, ai), "w")
    285                 print >>f, attr
    286                 f.close()
    287                 ai += 1
    288 
    289     def load(self, dir):
    290         if os.access("%s/me" % dir, os.R_OK):
    291             f = open("%s/me" % dir, "r")
    292             self.me = pickle.load(f)
    293             f.close()
    294         else:
    295             self.me = None
    296         if os.access("%s/key" % dir, os.R_OK):
    297             f = open("%s/key" % dir, "r")
    298             self.key = pickle.load(f)
    299             f.close()
    300         else:
    301             self.key = None
    302         f = open("%s/globals" % dir, "r")
    303         self.globals = pickle.load(f)
    304         f.close()
    305         self.context = ABAC.context()
    306         self.context.load_directory("%s/certs" % dir)
    307 
     379            rv += '\n%s <- %s' % (encode_role(c.head()), encode_role(c.tail()))
     380        self.lock.release()
     381        return rv
     382
Note: See TracChangeset for help on using the changeset viewer.