source: TI12-security/trunk/python/NDG/AttAuthority.py @ 737

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/NDG/AttAuthority.py@737
Revision 737, 28.7 KB checked in by pjkersha, 14 years ago (diff)

ndgSetup.sh: fixed slight typo.

mapConfig.xml: added pubKey tag to allow client to Attribute Authority to use it to encrypt
outbound messages to it.

ndgSessionClient.py:

  • include code to set public key of Attribute Authority so that Session Manager can encrypt

messages to it.

  • -r/--req-autho option now requires the AA WSDL URI. -a is now used to set the AA pub key
  • see previous point.

AttAuthorityIO.py:

  • Changed tag 'clntCert' to 'encrCert' so as to be consistent with SessionMgrIO.py code.

attAuthority_services_server.py:

  • Moved encrypt/decrypt code here from AttAuthority? class to be consistent with

sessionMgr_services_server.py.

AttAuthority?.py:

  • Now inherits from dict to allow convenient access to properties file parameters as dictionary

items.

  • Added code to include pubKey tag from mapConfig file in trustedHostInfo returned from

getTrustedHostInfo.

SessionMgrIO.py:

output XML.

  • Shifted test code into separate file in Tests/

SessionClient?.py:

  • Added aaPubKey to reqAuthorisation method - see above re. passing AA public key for

encryption of messages.

sessionMgr_services_server.py:

  • Changes to comments.

Session.py:

private key info of client to allow encrypt of responses from other WSs that SessionMgr? calls.
These are actually passed into CredWallet? instance of UserSession?.

  • AA Public key is passed into reqAuthorisation. This is written to a temp file for use by

XMLSec encryption code.

CredWallet?.py:

  • CredWalletAuthorisationDenied? - make sure extAttCertList gets set to []
  • Added pub/private functionality for encryption of messages to and from Attribute Authorities.
  • reqAuthorisation and getAATrustedHostInfo methods - read in client public key using

straight open/read: using X509Cert.asString() misses out the actual MIME encoded cert text(!)

  • Changed reqAuthorisation() - a required role is now optional with mapFromTrustedHosts flag set.

It does help though with finding a suitable AttCert? for mapping.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""NDG Attribute Authority handles security authentication and authorization
2
3NERC Data Grid Project
4
5P J Kershaw 15/04/05
6
7Copyright (C) 2005 CCLRC & NERC
8
9This software may be distributed under the terms of the Q Public License,
10version 1.0 or later.
11"""
12
13cvsID = '$Id$'
14
15import types
16
17
18# Create unique names for attribute certificates
19import tempfile
20import os
21
22# Alter system path for dynamic import of user roles class
23import sys
24
25# For parsing of properties file
26import cElementTree as ElementTree
27
28# X509 Certificate handling
29from X509 import *
30
31# NDG Attribute Certificate
32from AttCert import *
33
34# Format for XML messages passed over WS
35from AttAuthorityIO import *
36
37
38#_____________________________________________________________________________
39class AttAuthorityError(Exception):
40    """Exception handling for NDG Attribute Authority class."""
41   
42    def __init__(self, msg):
43        self.__msg = msg
44         
45    def __str__(self):
46        return self.__msg
47
48
49
50
51#_____________________________________________________________________________
52class AttAuthorityAccessDenied(AttAuthorityError):
53    """NDG Attribute Authority - access denied exception.
54
55    Raise from authorise method where no roles are available for the user
56    but that the request is otherwise valid.  In all other error cases raise
57    AttAuthorityError"""   
58    pass
59
60
61
62#_____________________________________________________________________________
63class AttAuthority(dict):
64
65    """NDG Attribute Authority - server for user authentication/authorization.
66    """
67
68    # Code designed from NERC Data Grid Enterprise and Information Viewpoint
69    # documents.
70    #
71    # Also, draws from Neil Bennett's ACServer class used in the Java
72    # implementation of NDG Security
73
74    # valid configuration property keywords
75    __validKeys = [ 'name',
76                    'keyFile',
77                    'keyPwd',
78                    'certFile',
79                    'caCertFile',
80                    'attCertLifeTime',
81                    'attCertNotBeforeOff',
82                    'attCertFilePfx',
83                    'attCertFileSfx',
84                    'mapConfigFile',
85                    'attCertDir',
86                    'dnSeparator',
87                    'usrRolesModFilePath',
88                    'usrRolesModName',
89                    'usrRolesClassName',
90                    'usrRolesPropFile']
91   
92    def __init__(self, propFilePath, bReadMapConfig=True):
93        """Create new NDG Attribute Authority instance
94
95        propFilePath:   path to file containing Attribute Authority
96                        configuration parameters.
97        bReadMapConfig: by default the Map Configuration file is read.  Set
98                        this flag to False to override.
99        """
100
101        # Base class initialisation
102        dict.__init__(self)
103       
104        if not isinstance(propFilePath, basestring):
105            raise AttAuthorityError("Input Properties file path " + \
106                                    "must be a valid string.")
107
108
109        # Initialise role mapping look-ups - These are set in readMapConfig()
110        self.__mapConfig = None
111        self.__localRole2Trusted = None
112        self.__trusted2LocalRole = None
113
114
115        # Configuration file properties are held together in a dictionary
116        self.__prop = {}
117
118        # Read Attribute Authority Properties file
119        self.readProperties(propFilePath)
120
121        # Read the Map Configuration file
122        if bReadMapConfig:
123            self.readMapConfig()
124
125        # Instantiate Certificate object
126        self.__cert = X509Cert(self.__prop['certFile'])
127        self.__cert.read()
128
129        # Check it's valid
130        try:
131            self.__cert.isValidTime(raiseExcep=True)
132           
133        except Exception, e:
134            raise AttAuthorityError(\
135                    "Attribute Authority's certificate is invalid: " + str(e))
136       
137        # Check CA certificate
138        caCert = X509Cert(self.__prop['caCertFile'])
139        caCert.read()
140       
141        try:
142            caCert.isValidTime(raiseExcep=True)
143           
144        except Exception, e:
145            raise AttAuthorityError("CA certificate is invalid: " + str(e))
146       
147        # Issuer details - serialise using the separator string set in the
148        # properties file
149        self.__issuer = \
150            self.__cert.dn.serialise(separator=self.__prop['dnSeparator'])
151
152        self.__issuerSerialNumber = self.__cert.serialNumber
153
154       
155        # Set-up user roles interface
156        try:
157            # Temporarily extend system path ready for import
158            sysPathBak = sys.path
159            sys.path.append(self.__prop['usrRolesModFilePath'])
160           
161            # Import module name specified in properties file
162            usrRolesMod = __import__(self.__prop['usrRolesModName'],
163                                     globals(),
164                                     locals(),
165                                     [self.__prop['usrRolesClassName']])
166
167            sys.path = sysPathBak
168           
169            usrRolesClass = eval('usrRolesMod.' + \
170                                 self.__prop['usrRolesClassName'])
171
172        except Exception, e:
173            raise AttAuthorityError('Importing User Roles module: %s' % e)
174
175        # Check class inherits from AAUserRoles abstract base class
176        if not issubclass(usrRolesClass, AAUserRoles):
177            raise AttAuthorityError(\
178                "User Roles class %s must be derived from AAUserRoles" % \
179                self.__prop['usrRolesClassName'])
180
181
182        # Instantiate custom class
183        try:
184            self.__usrRoles = usrRolesClass(self.__prop['usrRolesPropFile'])
185           
186        except Exception, e:
187            raise AttAuthorityError(\
188                "Error instantiating User Roles interface: " + str(e))
189     
190       
191    #_________________________________________________________________________
192    # Methods for Attribute Authority dictionary like behaviour       
193    def __delitem__(self, key):
194        self.__class__.__name__ + " keys cannot be removed"       
195        raise KeyError('Keys cannot be deleted from '+self.__class__.__name__)
196
197
198    def __getitem__(self, key):
199        self.__class__.__name__ + """ behaves as data dictionary of Attribute
200        Authority properties
201        """
202        if key not in self.__prop:
203            raise KeyError("Invalid key " + key)
204       
205        return self.__prop[key]
206       
207
208    def clear(self):
209        raise KeyError("Data cannot be cleared from "+self.__class__.__name__)
210   
211    def keys(self):
212        return self.__prop.keys()
213
214    def items(self):
215        return self.__prop.items()
216
217    def values(self):
218        return self.__prop.values()
219
220    def has_key(self, key):
221        return self.__prop.has_key(key)
222
223    # 'in' operator
224    def __contains__(self, key):
225        return key in self.__prop
226
227       
228    #_________________________________________________________________________
229    def authorise(self,
230                  reqXMLtxt=None, 
231                  proxyCertFilePath=None,
232                  userAttCertFilePath=None,
233                  **reqKeys):
234
235        """Request a new Attribute Certificate for authorisation
236
237        reqXMLtxt:              input keywords as tags in formatted XML string
238                                String must follow format for
239                                AttAuthorityIO.AuthorisationReq class to
240                                parse.
241                               
242        proxyCertFilePath|proxyCert:
243
244                                user's proxy certificate use appropriate
245                                keyword for input as a file path or as the
246                                text content respectively.
247                               
248                                Nb. proxyCert is set via reqKeys
249                               
250        userAttCertFilePath|userAttCert:
251       
252                                externally provided attribute certificate
253                                from another data centre.  This is only
254                                necessary if the user is not registered with
255                                this attribute authority.
256
257                                Pass in either the file path or a string
258                                containing the certificate XML content.
259                               
260                                Nb. userAttCert is set via reqKeys
261                                """
262
263        if reqXMLtxt is not None:
264            # Parse XML text into keywords corresponding to the input
265            # parameters
266            if not isinstance(reqXMLtxt, basestring):
267                raise AttAuthorityError(\
268                            "XML Authorisation request must be a string")
269                                       
270            # Parse and decrypt as necessary
271            try:
272                # 1st assume that the request was encrypted
273                reqKeys = AuthorisationReq(encrXMLtxt=reqXMLtxt,
274                                    encrPriKeyFilePath=self.__prop['keyFile'],
275                                    encrPriKeyPwd=self.__prop['keyPwd'])
276            except Exception, e:
277               
278                # Error occured decrypting - Trying parsing again, but this
279                # time assuming non-encrypted
280                try:
281                    reqKeys = AuthorisationReq(xmlTxt=reqXMLtxt)
282                   
283                except Exception, e:
284                    raise AttAuthorityError(\
285                        "Error parsing authorisation request: %s" % e)
286
287
288        # Read proxy certificate
289        try:
290            usrProxyCert = X509Cert()
291           
292            if proxyCertFilePath is not None and \
293               isinstance(proxyCertFilePath, basestring):
294
295                # Proxy Certificate input as a file
296                usrProxyCert.read(proxyCertFilePath)
297               
298            elif reqKeys['proxyCert'] is not None:
299
300                # Proxy Certificate input as string text
301                usrProxyCert.parse(reqKeys['proxyCert'])
302
303            else:
304                raise AttAuthorityError(\
305                    "no input proxy certificate file path or file text")
306           
307        except Exception, e:
308            raise AttAuthorityError("User Proxy Certificate: %s" % e)
309
310
311        # Check proxy certificate hasn't expired
312        try:
313            usrProxyCert.isValidTime(raiseExcep=True)
314           
315        except Exception, e:
316            raise AttAuthorityError("User Proxy Certificate is invalid: " + \
317                                    str(e))
318
319           
320        # Get Distinguished name from certificate as an X500DN type
321        usrDN = usrProxyCert.dn
322       
323       
324        # Make a new Attribute Certificate instance passing in certificate
325        # details for later signing
326        #
327        # Nb. new attribute certificate file path is created from the
328        # Credentials Repository
329        certFilePathList = [self.__prop['certFile'],self.__prop['caCertFile']]
330        attCert = AttCert(self.__newAttCertFilePath(),
331                          signingKeyFilePath=self.__prop['keyFile'],
332                          certFilePathList=certFilePathList)
333
334
335        # Set holder's (user's) Distinguished Name
336        try:
337            attCert['holder'] = \
338                        usrDN.serialise(separator=self.__prop['dnSeparator'])
339           
340        except Exception, e:
341            raise AttAuthorityError("User DN: %s" % e)
342
343       
344        # Set Issuer details from Attribute Authority
345        issuerDN = self.__cert.dn
346        try:
347            attCert['issuer'] = \
348                    issuerDN.serialise(separator=self.__prop['dnSeparator'])
349           
350        except Exception, e:
351            raise AttAuthorityError("Issuer DN: %s" % e)
352       
353        attCert['issuerName'] = self.__prop['name']
354        attCert['issuerSerialNumber'] = self.__issuerSerialNumber
355
356
357        # Set validity time
358        try:
359            attCert.setValidityTime(\
360                        lifeTime=self.__prop['attCertLifeTime'],
361                        notBeforeOffset=self.__prop['attCertNotBeforeOff'])
362
363            # Check against the proxy certificate's expiry
364            dtUsrProxyNotAfter = usrProxyCert.notAfter
365           
366            if attCert.getValidityNotAfter(asDatetime=True) > \
367               dtUsrProxyNotAfter:
368
369                # Adjust the attribute certificate's expiry date time
370                # so that it agrees with that of the proxy certificate
371                attCert.setValidityTime(dtNotAfter=dtUsrProxyNotAfter)
372           
373        except Exception, e:
374            raise AttAuthorityError("Error setting validity time: %s" % e)
375       
376
377        # Check name is registered with this Attribute Authority - if no
378        # user roles are found, the user is not registered
379        usrRoles = self.getRoles(str(usrDN))
380        if usrRoles:           
381            # Set as an Original Certificate
382            #
383            # User roles found - user is registered with this data centre
384            # Add roles for this user for this data centre
385            attCert.addRoles(usrRoles)
386
387            # Mark new Attribute Certificate as an original
388            attCert['provenance'] = 'original'
389
390        else:           
391            # Set as a Mapped Certificate
392            #
393            # No roles found - user is not registered with this data centre
394            # Check for an externally provided certificate from another
395            # trusted data centre
396            if userAttCertFilePath:
397               
398                # Read externally provided certificate
399                try:
400                    extAttCert = AttCertRead(userAttCertFilePath)
401                   
402                except Exception, e:
403                    raise AttAuthorityError(\
404                            "Reading external Attribute Certificate: %s" + e)
405                               
406            elif 'userAttCert' in reqKeys and reqKeys['userAttCert']:
407                extAttCert = reqKeys['userAttCert']
408               
409            else:
410                raise AttAuthorityAccessDenied(\
411                    "User \"%s\" is not registered " % attCert['holder'] + \
412                    "and no external attribute certificate is available " + \
413                    "to make a mapping.")
414
415
416            # Check it's an original certificate - mapped certificates can't
417            # be used to make further mappings
418            if extAttCert.isMapped():
419                raise AttAuthorityError(\
420                    "External Attribute Certificate must have an " + \
421                    "original provenance in order to make further mappings.")
422
423
424            # Check it's valid and signed
425            try:
426                # Give path to CA cert to allow check
427                extAttCert.isValid(raiseExcep=True,
428                                   certFilePathList=self.__prop['caCertFile'])
429               
430            except Exception, e:
431                raise AttAuthorityError(\
432                            "Invalid Remote Attribute Certificate: %s" + e)       
433
434
435            # Check that's it's holder matches the user certificate DN
436            try:
437                holderDN = X500DN(dn=extAttCert['holder'])
438               
439            except Exception, e:
440                raise AttAuthorityError(\
441                    "Error creating X500DN for holder: %s" + e)
442           
443            if holderDN != usrDN:
444                raise AttAuthorityError(\
445                    "User certificate and Attribute Certificate DNs " + \
446                    "don't match: " + str(usrDN) + " and " + str(holderDN))
447           
448 
449            # Get roles from external Attribute Certificate
450            trustedHostRoles = extAttCert.getRoles()
451
452
453            # Map external roles to local ones
454            localRoles = self.mapTrusted2LocalRoles(extAttCert['issuerName'],
455                                                    trustedHostRoles)
456            if not localRoles:
457                raise AttAuthorityAccessDenied(\
458                    "No local roles mapped to the %s roles: %s" % \
459                    (extAttCert['issuerName'], str(trustedHostRoles)))
460
461            attCert.addRoles(localRoles)
462           
463           
464            # Mark new Attribute Certificate as mapped
465            attCert['provenance'] = 'mapped'
466
467            # End set mapped certificate block
468           
469
470        try:
471            # Digitally sign certificate using Attribute Authority's
472            # certificate and private key
473            attCert.sign(signingKeyPwd=self.__prop['keyPwd'])
474           
475            # Check the certificate is valid
476            attCert.isValid(raiseExcep=True)
477           
478            # Write out certificate to keep a record of it for auditing
479            attCert.write()
480
481            # Return the cert to caller
482            return attCert
483       
484        except Exception, e:
485            raise AttAuthorityError("New Attribute Certificate \"%s\": %s" % \
486                                    (attCert.filePath, e))
487
488   
489
490
491    def readProperties(self, propFilePath=None):
492
493        """Read the configuration properties for the Attribute Authority
494
495        propFilePath: file path to properties file
496        """
497       
498        if propFilePath is not None:
499            if not isinstance(propFilePath, basestring):
500                raise AttAuthorityError("Input Properties file path " + \
501                                        "must be a valid string.")
502           
503            self.__propFilePath = propFilePath
504
505
506        try:
507            tree = ElementTree.parse(self.__propFilePath)
508           
509        except IOError, ioErr:
510            raise AttAuthorityError(\
511                                "Error parsing properties file \"%s\": %s" % \
512                                (ioErr.filename, ioErr.strerror))
513
514       
515        aaProp = tree.getroot()
516
517        # Copy properties from file as member variables
518        prop = dict([(elem.tag, elem.text) for elem in aaProp])
519
520
521        # Check for missing properties
522        propKeys = prop.keys()
523        missingKeys = [key for key in AttAuthority.__validKeys \
524                       if key not in propKeys]
525        if missingKeys != []:
526            raise AttAuthorityError("The following properties are " + \
527                                    "missing from the properties file: " + \
528                                    ', '.join(missingKeys))
529
530        # Strip white space - apart from fields where may be required
531        for key in prop:
532            if key != 'keyPwd' and prop[key]: 
533                prop[key] = prop[key].strip()
534               
535            # Check for environment variables in file paths
536            tagCaps = key.upper()
537            if 'FILE' in tagCaps or 'PATH' in tagCaps or 'DIR' in tagCaps:
538                prop[key] = os.path.expandvars(prop[key])
539 
540 
541        # Ensure Certificate time parameters are converted to numeric type
542        prop['attCertLifeTime'] = float(prop['attCertLifeTime'])
543        prop['attCertNotBeforeOff'] = float(prop['attCertNotBeforeOff'])
544         
545        self.__prop = prop
546
547       
548        # Check directory path
549        try:
550            dirList = os.listdir(self.__prop['attCertDir'])
551
552        except OSError, osError:
553            raise AttAuthorityError(\
554                "Invalid directory path Attribute Certificates store: " + \
555                osError.strerror)
556
557       
558       
559       
560    def readMapConfig(self, mapConfigFilePath=None):
561        """Parse Map Configuration file.
562
563        mapConfigFilePath:  file path for map configuration file.  If omitted,
564                            use member variable __mapConfigFilePath.
565        """
566       
567        if mapConfigFilePath is not None:
568            if not isinstance(mapConfigFilePath, basestring):
569                raise AttAuthorityError("Input Map Configuration file path "+\
570                                        "must be a valid string.")
571           
572            self.__prop['mapConfigFile'] = mapConfigFilePath
573
574       
575        tree = ElementTree.parse(self.__prop['mapConfigFile'])
576        rootElem = tree.getroot()
577
578        trustedElem = rootElem.findall('trusted')
579
580        # Dictionaries:
581        # 1) to hold all the data
582        self.__mapConfig = {}
583
584        # ... look-up
585        # 2) hosts corresponding to a given role and
586        # 3) roles of external data centre to this data centre
587        self.__localRole2TrustedHost = {}
588        self.__localRole2Trusted = {}
589        self.__trusted2LocalRole = {}
590       
591        for elem in trustedElem:
592
593            roleElem = elem.findall('role')
594            if not roleElem:
595                raise AttAuthorityError("\"role\" tag not found in \"%s\"" % \
596                                        self.__prop['mapConfigFile'])
597
598            try:
599                trustedHost = elem.attrib.values()[0]
600               
601            except Exception, e:
602                raise AttAuthorityError(\
603                                    "Error setting trusted host name: %s" % e)
604
605           
606            # Add signatureFile and list of roles
607            self.__mapConfig[trustedHost] = \
608            {
609                'wsdl': elem.findtext('wsdl'),
610                'pubKey': elem.findtext('pubKey'),
611                'role': [dict(i.items()) for i in roleElem]
612            }
613
614                   
615            self.__localRole2Trusted[trustedHost] = {}
616            self.__trusted2LocalRole[trustedHost] = {}
617           
618            for role in self.__mapConfig[trustedHost]['role']:
619
620                localRole = role['local']
621                remoteRole = role['remote']
622               
623                # Role to host look-up
624                if localRole in self.__localRole2TrustedHost:
625                   
626                    if trustedHost not in \
627                       self.__localRole2TrustedHost[localRole]:
628                        self.__localRole2TrustedHost[localRole].\
629                                                        append(trustedHost)                       
630                else:
631                    self.__localRole2TrustedHost[localRole] = [trustedHost]
632
633
634                # Trusted Host to local role and trusted host to trusted role
635                # map look-ups
636                try:
637                    self.__trusted2LocalRole[trustedHost][remoteRole].append(\
638                                                                localRole)                 
639                except KeyError:
640                    self.__trusted2LocalRole[trustedHost][remoteRole] = \
641                                                                [localRole]
642                   
643                try:
644                    self.__localRole2Trusted[trustedHost][localRole].append(\
645                                                                remoteRole)                 
646                except KeyError:
647                    self.__localRole2Trusted[trustedHost][localRole] = \
648                                                                [remoteRole]                 
649 
650
651           
652    def usrIsRegistered(self, usrDN):
653        """Check a particular user is registered with the Data Centre that the
654        Attribute Authority represents"""
655        return self.__usrRoles.usrIsRegistered(usrDN)
656       
657
658
659
660
661    def getRoles(self, dn):
662        """Get the roles available to the registered user identified usrDN.
663        """
664
665        # Call to AAUserRoles derived class.  Each Attribute Authority
666        # should define it's own roles class derived from AAUserRoles to
667        # define how roles are accessed
668        try:
669            return self.__usrRoles.getRoles(dn)
670
671        except Exception, e:
672            raise AttAuthorityError("Getting user roles: %s" % e)
673
674
675
676   
677    def getTrustedHostInfo(self, **reqKeys):
678        """Return a dictionary of the hosts that have trust relationships
679        with this AA.  The dictionary is indexed by the trusted host name
680        and contains WSDL URIs and the roles that map to the
681        given input local role.
682
683        If no role is input, return all the AA's trusted hosts with all
684        their possible roles
685
686        Returns None if role isn't recognised"""
687                                         
688        if not self.__localRole2Trusted:
689            raise AttAuthorityError("Roles to host look-up is not set - " + \
690                                    "ensure readMapConfig() has been called.")
691
692
693        if 'role' not in reqKeys:
694            # No role input - return all trusted hosts with their WSDL URIs
695            # and roles
696            trustedHostInfo = dict([\
697               (k, \
698                {'wsdl': v['wsdl'], \
699                 'pubKey': v['pubKey'], \
700                 'role': [role['remote'] for role in v['role']]}) \
701                for k, v in self.__mapConfig.items()])
702        else:           
703            # Get trusted hosts for given input local role       
704            try:
705                trustedHosts = self.__localRole2TrustedHost[reqKeys['role']]
706            except:
707                return None
708   
709   
710            # Get associated WSDL URI and roles for the trusted hosts
711            # identified and return as a dictionary indexed by host name
712            trustedHostInfo = dict([(host, \
713                {'wsdl': self.__mapConfig[host]['wsdl'], \
714                 'pubKey': self.__mapConfig[host]['pubKey'], \
715                 'role': self.__localRole2Trusted[host][reqKeys['role']]}) \
716                 for host in trustedHosts])
717                         
718        return trustedHostInfo
719
720
721
722
723    def mapTrusted2LocalRoles(self, trustedHost, trustedHostRoles):
724        """Map roles of trusted hosts to roles for this data centre
725
726        trustedHost:        name of external trusted data centre
727        trustedHostRoles:   list of external roles to map"""
728
729        if not self.__trusted2LocalRole:
730            raise AttAuthorityError("Roles map is not set - ensure " + \
731                                    "readMapConfig() has been called.")
732
733
734        # Check the host name is a trusted one recorded in the map
735        # configuration
736        if not self.__trusted2LocalRole.has_key(trustedHost):
737            return []
738
739        # Add local roles, skipping if no mapping is found
740        localRoles = []
741        for trustedRole in trustedHostRoles:
742            if trustedRole in self.__trusted2LocalRole[trustedHost]:
743                localRoles.extend(\
744                        self.__trusted2LocalRole[trustedHost][trustedRole])
745               
746        return localRoles
747
748
749
750
751    def __newAttCertFilePath(self):
752        """Create a new unique attribute certificate file path"""
753       
754        attCertFd, attCertFilePath = \
755                   tempfile.mkstemp(suffix=self.__prop['attCertFileSfx'],
756                                    prefix=self.__prop['attCertFilePfx'],
757                                    dir=self.__prop['attCertDir'],
758                                    text=True)
759
760        # The file is opened - close using the file descriptor returned in the
761        # first element of the tuple
762        os.close(attCertFd)
763
764        # The file path is the 2nd element
765        return attCertFilePath
766
767
768
769
770#_____________________________________________________________________________
771class AAUserRolesError(Exception):
772
773    """Exception handling for NDG Attribute Authority User Roles interface
774    class."""
775   
776    def __init__(self, msg):
777        self.__msg = msg
778         
779    def __str__(self):
780        return self.__msg
781
782
783
784#_____________________________________________________________________________
785class AAUserRoles:
786
787    """An abstract base class to define the user roles interface to an
788    Attribute Authority.
789
790    Each NDG data centre should implement a derived class which implements
791    the way user roles are provided to its representative Attribute Authority.
792   
793    Roles are expected to indexed by user Distinguished Name (DN).  They
794    could be stored in a database or file."""
795
796    # User defined class may wish to specify a URI for a database interface or
797    # path for a user roles configuration file
798    def __init__(self, dbURI=None, filePath=None):
799        """User Roles abstract base class - derive from this class to define
800        roles interface to Attribute Authority"""
801        raise NotImplementedError(\
802            self.__init__.__doc__.replace('\n       ',''))
803
804
805    def usrIsRegistered(self, dn):
806        """Derived method should return True if user is known otherwise
807        False"""
808        raise NotImplementedError(
809            self.UserIsRegistered.__doc__.replace('\n       ',''))
810
811
812    def getRoles(self, dn):
813        """Derived method should return the roles for the given user's
814        DN or else raise an exception"""
815        raise NotImplementedError(
816            self.getRoles.__doc__.replace('\n       ',''))
817
818
819#_____________________________________________________________________________
820# Test routines
821def testGetTrustedHostInfo(role=None,
822                           propFilePath='./attAuthorityProperties.xml'):
823    "Test getTrustedHosts AttAuthority method"
824    import pdb
825    pdb.set_trace()
826   
827    try:
828        aa = AttAuthority(propFilePath)
829        return aa.getTrustedHostInfo(role)
830   
831    except Exception, e:
832        print e
Note: See TracBrowser for help on using the repository browser.