source: TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/credentialwallet.py @ 6673

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/credentialwallet.py@6673
Revision 6673, 27.5 KB checked in by pjkersha, 11 years ago (diff)

Started pruning trunk of old security code. None of this code is used by the current system but it remains in the code base and is still unit tested:

  • NDG Attribute Certificate (replaced by SAML assertions)
  • SOAP/WSDL interfaces (replaced by SAML over SOAP)
  • Attribute Authority get NDG Attribute Certificate interface (replaced with SAML AttributeQuery/Response)
  • Session Manager (separate web service not needed for session management, new system uses Beaker to achieve much the same thing)
  • NDG Credential Wallet (SAML replacement)
  • WS-Security (replaced by SSL with client Authentication). WS-Security code is now in a separate WSSecurity branch to be released as a separate egg.
  • ndg.security.common.XMLSec (no digital signature needed for SAML currently but may need to be revived later. This code uses PyXML which breaks with Python >= 2.5.5. If revived it should be implemented with 4Suite-XML or ElementTree or lxml
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1"""Credential Wallet classes
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "30/11/05"
7__copyright__ = "(C) 2009 Science and Technology Facilities Council"
8__license__ = "BSD - see LICENSE file in top-level directory"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = '$Id:credentialwallet.py 4378 2008-10-29 10:30:14Z pjkersha $'
11
12import logging
13log = logging.getLogger(__name__)
14logging.basicConfig(level=logging.DEBUG)
15
16import os
17import warnings
18import traceback
19
20# Check Attribute Certificate validity times
21from datetime import datetime, timedelta
22
23from ConfigParser import ConfigParser
24
25from ndg.saml.utils import SAMLDateTime
26from ndg.saml.saml2.core import Assertion
27
28# Access Attribute Authority's web service using ZSI - allow pass if not
29# loaded since it's possible to make AttributeAuthority instance locally
30# without using the WS
31aaImportError = True
32try:
33    # AttributeAuthority client package resides with CredentialWallet module in
34    # ndg.security.common
35    from ndg.security.common.attributeauthority import (
36        AttributeAuthorityClient, AttributeAuthorityClientError, 
37        AttributeRequestDenied, NoMatchingRoleInTrustedHosts)
38    aaImportError = False
39except ImportError:
40    pass
41
42# Likewise - may not want to use WS and use AttributeAuthority locally in which
43# case no need to import it
44try:
45    from ndg.security.server.attributeauthority import (AttributeAuthority, 
46        AttributeAuthorityError, AttributeAuthorityAccessDenied)
47    aaImportError = False
48except ImportError:
49    pass
50
51if aaImportError:
52    raise ImportError("Either AttributeAuthority or AttributeAuthorityClient "
53                      "classes must be present to allow interoperation with "
54                      "Attribute Authorities: %s" % traceback.format_exc())
55
56# Authentication X.509 Certificate
57from ndg.security.common.X509 import X509Cert
58from M2Crypto import X509, BIO, RSA
59
60# Authorisation - attribute certificate
61from ndg.security.common.AttCert import AttCert, AttCertError
62from ndg.security.common.wssecurity.signaturehandler.dom import SignatureHandler
63
64# generic parser to read INI/XML properties file
65from ndg.security.common.utils.configfileparsers import \
66                                                INIPropertyFileWithValidation
67
68from ndg.security.common.utils import TypedList
69from ndg.security.common.utils.configfileparsers import (     
70                                                    CaseSensitiveConfigParser,)
71
72
73class _CredentialWalletException(Exception):   
74    """Generic Exception class for CredentialWallet module.  Overrides
75    Exception to enable writing to the log"""
76    def __init__(self, *arg, **kw):
77        if len(arg) > 0:
78            log.error(arg[0])
79           
80        Exception.__init__(self, *arg, **kw)
81
82
83class CredentialWalletError(_CredentialWalletException):   
84    """Exception handling for NDG Credential Wallet class.  Overrides Exception
85    to enable writing to the log"""
86
87
88class CredentialWalletAttributeRequestDenied(CredentialWalletError):   
89    """Handling exception where CredentialWallet is denied authorisation by an
90    Attribute Authority.
91 
92    @type __extAttCertList: list
93    @ivar __extAttCertList: list of candidate Attribute Certificates that
94    could be used to try to get a mapped certificate from the target
95    Attribute Authority
96   
97    @type __trustedHostInfo: dict
98    @ivar __trustedHostInfo: dictionary indexed by host name giving
99    details of Attribute Authority URI and roles for trusted hosts"""
100   
101    def __init__(self, *args, **kw):
102        """Raise exception for attribute request denied with option to give
103        caller hint to certificates that could used to try to obtain a
104        mapped certificate
105       
106        @type extAttCertList: list
107        @param extAttCertList: list of candidate Attribute Certificates that
108        could be used to try to get a mapped certificate from the target
109        Attribute Authority
110       
111        @type trustedHostInfo: dict
112        @param trustedHostInfo: dictionary indexed by host name giving
113        details of Attribute Authority URI and roles for trusted hosts"""
114       
115        self.__trustedHostInfo = kw.pop('trustedHostInfo', {})
116        self.__extAttCertList = kw.pop('extAttCertList', [])
117           
118        CredentialWalletError.__init__(self, *args, **kw)
119
120    def _getTrustedHostInfo(self):
121        """Get message text"""
122        return self.__trustedHostInfo
123
124    trustedHostInfo = property(fget=_getTrustedHostInfo, 
125                               doc="URI and roles details for trusted hosts")
126       
127    def _getExtAttCertList(self):
128        """Return list of candidate Attribute Certificates that could be used
129        to try to get a mapped certificate from the target Attribute Authority
130        """
131        return self.__extAttCertList
132
133    extAttCertList = property(fget=_getExtAttCertList,
134                              doc="list of candidate Attribute Certificates "
135                              "that could be used to try to get a mapped "
136                              "certificate from the target Attribute "
137                              "Authority")
138
139         
140class _MetaCredentialWallet(type):
141    """Enable CredentialWallet to have read only class variables e.g.
142   
143    print CredentialWallet.accessDenied
144   
145    ... is allowed but,
146   
147    CredentialWallet.accessDenied = None
148   
149    ... raises - AttributeError: can't set attribute"""
150   
151    def _getAccessDenied(cls):
152        '''accessDenied get method'''
153        return False
154   
155    accessDenied = property(fget=_getAccessDenied)
156   
157    def _getAccessGranted(cls):
158        '''accessGranted get method'''
159        return True
160   
161    accessGranted = property(fget=_getAccessGranted)
162
163class CredentialContainer(object):
164    """Container for cached credentials"""
165    ID_ATTRNAME = 'id'
166    ITEM_ATTRNAME = 'credential'
167    ISSUERNAME_ATTRNAME = 'issuerName'
168    ATTRIBUTE_AUTHORITY_URI_ATTRNAME = 'attributeAuthorityURI'
169    CREDENTIAL_TYPE_ATTRNAME = 'type'
170   
171    __ATTRIBUTE_NAMES = (
172        ID_ATTRNAME,
173        ITEM_ATTRNAME,
174        ISSUERNAME_ATTRNAME,
175        ATTRIBUTE_AUTHORITY_URI_ATTRNAME,
176        CREDENTIAL_TYPE_ATTRNAME
177    )
178    __slots__ = tuple(["__%s" % n for n in __ATTRIBUTE_NAMES])
179   
180    def __init__(self, type=None):
181        self.__type = None
182        self.type = type
183       
184        self.__id = -1
185        self.__credential = None
186        self.__issuerName = None
187        self.__attributeAuthorityURI = None
188
189    def _getType(self):
190        return self.__type
191
192    def _setType(self, value):
193        if not isinstance(value, type):
194            raise TypeError('Expecting %r for "type" attribute; got %r' %
195                            (type, type(value)))       
196        self.__type = value
197
198    type = property(_getType, _setType, 
199                    doc="Type for credential - set to None for any type")
200
201    def _getId(self):
202        return self.__id
203
204    def _setId(self, value):
205        if not isinstance(value, int):
206            raise TypeError('Expecting int type for "id" attribute; got %r' %
207                            type(value))
208        self.__id = value
209
210    id = property(_getId, 
211                  _setId, 
212                  doc="Numbered identifier for credential - "
213                      "set to -1 for new credentials")
214
215    def _getCredential(self):
216        return self.__credential
217
218    def _setCredential(self, value):
219        # Safeguard type attribute referencing for unpickling process - this
220        # method may be called before type attribute has been set
221        _type = getattr(self, 
222                        CredentialContainer.CREDENTIAL_TYPE_ATTRNAME, 
223                        None)
224       
225        if _type is not None and not isinstance(value, _type):
226            raise TypeError('Expecting %r type for "credential" attribute; '
227                            'got %r' % type(value))
228        self.__credential = value
229
230    credential = property(_getCredential, 
231                          _setCredential, 
232                          doc="Credential object")
233
234    def _getIssuerName(self):
235        return self.__issuerName
236
237    def _setIssuerName(self, value):
238        self.__issuerName = value
239
240    issuerName = property(_getIssuerName, 
241                          _setIssuerName, 
242                          doc="Name of issuer of the credential")
243
244    def _getAttributeAuthorityURI(self):
245        return self.__attributeAuthorityURI
246
247    def _setAttributeAuthorityURI(self, value):
248        """String or None type are allowed - The URI may be set to None if
249        a local Attribute Authority instance is being invoked rather
250        one hosted via a remote URI
251        """
252        if not isinstance(value, (basestring, type(None))):
253            raise TypeError('Expecting string or None type for '
254                            '"attributeAuthorityURI"; got %r instead' % 
255                            type(value))
256        self.__attributeAuthorityURI = value
257
258    attributeAuthorityURI = property(_getAttributeAuthorityURI,
259                                     _setAttributeAuthorityURI, 
260                                     doc="Attribute Authority Service URI")
261
262    def __getstate__(self):
263        '''Enable pickling'''
264        thisDict = dict([(attrName, getattr(self, attrName))
265                         for attrName in CredentialContainer.__ATTRIBUTE_NAMES])
266       
267        return thisDict
268       
269    def __setstate__(self, attrDict):
270        '''Enable pickling for use with beaker.session'''
271        try:
272            for attr, val in attrDict.items():
273                setattr(self, attr, val)
274        except Exception, e:
275            pass
276       
277
278class CredentialWalletBase(object):
279    """Abstract base class for NDG and SAML Credential Wallet implementations
280    """ 
281    CONFIG_FILE_OPTNAMES = ("userId", )
282    __slots__ = ("__credentials", "__credentialsKeyedByURI", "__userId")
283   
284    def __init__(self):
285        self.__userId = None
286        self.__credentials = {}
287        self.__credentialsKeyedByURI = {}
288
289    @classmethod
290    def fromConfig(cls, cfg, **kw):
291        '''Alternative constructor makes object from config file settings
292        @type cfg: basestring /ConfigParser derived type
293        @param cfg: configuration file path or ConfigParser type object
294        @rtype: ndg.security.common.credentialWallet.SAMLCredentialWallet
295        @return: new instance of this class
296        '''
297        credentialWallet = cls()
298        credentialWallet.parseConfig(cfg, **kw)
299       
300        return credentialWallet
301
302    def parseConfig(self, cfg, prefix='', section='DEFAULT'):
303        '''Virtual method defines interface to read config file settings
304        @type cfg: basestring /ConfigParser derived type
305        @param cfg: configuration file path or ConfigParser type object
306        @type prefix: basestring
307        @param prefix: prefix for option names e.g. "certExtApp."
308        @type section: baestring
309        @param section: configuration file section from which to extract
310        parameters.
311        '''
312        raise NotImplementedError(CredentialWalletBase.parseConfig.__doc__)
313
314    def addCredential(self, 
315                      credential, 
316                      attributeAuthorityURI=None,
317                      bUpdateCredentialRepository=True):
318        """Add a new attribute certificate to the list of credentials held.
319
320        @type credential: determined by derived class implementation e.g.
321        SAML assertion
322        @param credential: new attribute Certificate to be added
323        @type attributeAuthorityURI: basestring
324        @param attributeAuthorityURI: input the Attribute Authority URI from
325        which credential was retrieved.  This is added to a dict to enable
326        access to a given Attribute Certificate keyed by Attribute Authority
327        URI. See the getCredential method.
328        @type bUpdateCredentialRepository: bool
329        @param bUpdateCredentialRepository: if set to True, and a repository
330        exists it will be updated with the new credentials also
331       
332        @rtype: bool
333        @return: True if certificate was added otherwise False.  - If an
334        existing certificate from the same issuer has a later expiry it will
335        take precedence and the new input certificate is ignored."""
336        raise NotImplementedError(CredentialWalletBase.addCredential.__doc__)
337           
338    def audit(self):
339        """Check the credentials held in the wallet removing any that have
340        expired or are otherwise invalid."""
341        raise NotImplementedError(CredentialWalletBase.audit.__doc__)
342
343    def updateCredentialRepository(self, auditCred=True):
344        """Copy over non-persistent credentials held by wallet into the
345        perminent repository.
346       
347        @type auditCred: bool
348        @param auditCred: filter existing credentials in the repository
349        removing invalid ones"""
350        raise NotImplementedError(
351                    CredentialWalletBase.updateCredentialRepository.__doc__)
352       
353    def _getCredentials(self):
354        """Get Property method.  Credentials dict is read-only but also see
355        addCredential method
356       
357        @rtype: dict
358        @return: cached ACs indesed by issuing organisation name"""
359        return self.__credentials
360
361    # Publish attribute
362    credentials = property(fget=_getCredentials,
363                           doc="List of credentials linked to issuing "
364                               "authorities")
365
366    def _getCredentialsKeyedByURI(self):
367        """Get Property method for credentials keyed by Attribute Authority URI
368        Credentials dict is read-only but also see addCredential method
369       
370        @rtype: dict
371        @return: cached ACs indexed by issuing Attribute Authority"""
372        return self.__credentialsKeyedByURI
373   
374    # Publish attribute
375    credentialsKeyedByURI = property(fget=_getCredentialsKeyedByURI,
376                                     doc="List of Attribute Certificates "
377                                         "linked to attribute authority URI")
378       
379    def _getUserId(self):
380        return self.__userId
381
382    def _setUserId(self, value):
383        if not isinstance(value, basestring):
384            raise TypeError('Expecting string type for "userId"; got %r '
385                            'instead' % type(value))
386        self.__userId = value
387
388    userId = property(_getUserId, _setUserId, 
389                      doc="User Identity for this wallet")
390
391    def __getstate__(self):
392        '''Enable pickling for use with beaker.session'''
393        _dict = {}
394        for attrName in CredentialWalletBase.__slots__:
395            # Ugly hack to allow for derived classes setting private member
396            # variables
397            if attrName.startswith('__'):
398                attrName = "_CredentialWalletBase" + attrName
399               
400            _dict[attrName] = getattr(self, attrName)
401           
402        return _dict
403 
404    def __setstate__(self, attrDict):
405        '''Enable pickling for use with beaker.session'''
406        for attrName, val in attrDict.items():
407            setattr(self, attrName, val)
408
409
410class SAMLCredentialWallet(CredentialWalletBase):
411    """CredentialWallet for Earth System Grid supporting caching of SAML
412    Attribute Assertions
413    """
414    CONFIG_FILE_OPTNAMES = CredentialWalletBase.CONFIG_FILE_OPTNAMES + (
415                           "clockSkewTolerance", )
416    __slots__ = ("__clockSkewTolerance",)
417   
418    CREDENTIAL_REPOSITORY_NOT_SUPPORTED_MSG = ("SAMLCredentialWallet doesn't "
419                                               "support the "
420                                               "CredentialRepository "
421                                               "interface")
422
423    def __init__(self):
424        super(SAMLCredentialWallet, self).__init__()
425        self.__clockSkewTolerance = timedelta(seconds=0.)
426
427    def _getClockSkewTolerance(self):
428        return self.__clockSkewTolerance
429
430    def _setClockSkewTolerance(self, value):
431        if isinstance(value, (float, int, long)):
432            self.__clockSkewTolerance = timedelta(seconds=value)
433           
434        elif isinstance(value, basestring):
435            self.__clockSkewTolerance = timedelta(seconds=float(value))
436        else:
437            raise TypeError('Expecting float, int, long or string type for '
438                            '"clockSkewTolerance"; got %r' % type(value))
439
440    clockSkewTolerance = property(_getClockSkewTolerance, 
441                                  _setClockSkewTolerance, 
442                                  doc="Allow a tolerance (seconds) for "
443                                      "checking timestamps of the form: "
444                                      "notBeforeTime - tolerance < now < "
445                                      "notAfterTime + tolerance")
446
447    def parseConfig(self, cfg, prefix='', section='DEFAULT'):
448        '''Read config file settings
449        @type cfg: basestring /ConfigParser derived type
450        @param cfg: configuration file path or ConfigParser type object
451        @type prefix: basestring
452        @param prefix: prefix for option names e.g. "certExtApp."
453        @type section: baestring
454        @param section: configuration file section from which to extract
455        parameters.
456        ''' 
457        if isinstance(cfg, basestring):
458            cfgFilePath = os.path.expandvars(cfg)
459            _cfg = CaseSensitiveConfigParser()
460            _cfg.read(cfgFilePath)
461           
462        elif isinstance(cfg, ConfigParser):
463            _cfg = cfg   
464        else:
465            raise AttributeError('Expecting basestring or ConfigParser type '
466                                 'for "cfg" attribute; got %r type' % type(cfg))
467       
468        prefixLen = len(prefix)
469        for optName, val in _cfg.items(section):
470            if prefix and optName.startswith(prefix):
471                optName = optName[prefixLen:]
472               
473            setattr(self, optName, val)
474
475    def addCredential(self, 
476                      credential, 
477                      attributeAuthorityURI=None,
478                      bUpdateCredentialRepository=False,
479                      verifyCredential=True):
480        """Add a new assertion to the list of assertion credentials held.
481
482        @type credential: SAML assertion
483        @param credential: new assertion to be added
484        @type attributeAuthorityURI: basestring
485        @param attributeAuthorityURI: input the Attribute Authority URI from
486        which credential was retrieved.  This is added to a dict to enable
487        access to a given Attribute Certificate keyed by Attribute Authority
488        URI. See the getCredential method.
489        @type bUpdateCredentialRepository: bool
490        @param bUpdateCredentialRepository: if set to True, and a repository
491        exists it will be updated with the new credentials also. Nb. a derived
492        class will need to be implemented to enable this capability - see
493        the updateCredentialRepository method.
494        @type verifyCredential: bool
495        @param verifyCredential: if set to True, test validity of credential
496        by calling isValidCredential method.
497       
498        @rtype: bool
499        @return: True if credential was added otherwise False.  - If an
500        existing certificate from the same issuer has a later expiry it will
501        take precedence and the new input certificate is ignored."""
502       
503        # Check input
504        if not isinstance(credential, Assertion):
505            raise CredentialWalletError("Input credential must be an "
506                                        "%r type object" % Assertion)       
507
508        if verifyCredential and not self.isValidCredential(credential):
509            raise CredentialWalletError("Validity time error with assertion %r"
510                                        % credential)
511       
512        # Check to see if there is an existing Attribute Certificate held
513        # that was issued by the same host.  If so, compare the expiry time.
514        # The one with the latest expiry will be retained and the other
515        # ignored
516        bUpdateCred = True
517        if credential.issuer is None:
518            raise AttributeError("Adding SAML assertion to wallet: no issuer "
519                                 "set")
520           
521        issuerName = credential.issuer.value
522       
523        if issuerName in self.credentials:
524            # There is an existing certificate held with the same issuing
525            # host name as the new certificate
526            credentialOld = self.credentials[issuerName].credential
527
528            # If the new certificate has an earlier expiry time then ignore it
529            bUpdateCred = (credential.conditions.notOnOrAfter > 
530                           credentialOld.conditions.notOnOrAfter)
531
532        if bUpdateCred:
533            thisCredential = CredentialContainer(Assertion)
534            thisCredential.credential = credential
535            thisCredential.issuerName = issuerName
536            thisCredential.attributeAuthorityURI = attributeAuthorityURI
537           
538            self.credentials[issuerName] = thisCredential
539           
540            if attributeAuthorityURI:
541                self.credentialsKeyedByURI[
542                    attributeAuthorityURI] = thisCredential
543
544            # Update the Credentials Repository - the permanent store of user
545            # authorisation credentials.  This allows credentials for previous
546            # sessions to be re-instated
547            if bUpdateCredentialRepository:
548                self.updateCredentialRepository()
549
550        # Flag to caller to indicate whether the input certificate was added
551        # to the credentials or an exsiting certificate from the same issuer
552        # took precedence
553        return bUpdateCred
554                       
555    def audit(self):
556        """Check the credentials held in the wallet removing any that have
557        expired or are otherwise invalid."""
558
559        log.debug("SAMLCredentialWallet.audit ...")
560       
561        for issuerName, issuerEntry in self.credentials.items():
562            if not self.isValidCredential(issuerEntry.credential):
563                self.credentialsKeyedByURI.pop(
564                    issuerEntry.attributeAuthorityURI,
565                    None)
566                   
567                del self.credentials[issuerName]
568
569    def updateCredentialRepository(self, auditCred=True):
570        """No Credential Repository support is required"""
571        msg = SAMLCredentialWallet.CREDENTIAL_REPOSITORY_NOT_SUPPORTED_MSG
572        log.warning(msg)
573        warnings.warn(msg)
574
575    def isValidCredential(self, assertion):
576        """Validate SAML assertion time validity"""
577        utcNow = datetime.utcnow()
578        if utcNow < assertion.conditions.notBefore - self.clockSkewTolerance:
579            msg = ('The current clock time [%s] is before the SAML Attribute '
580                   'Response assertion conditions not before time [%s] ' 
581                   '(with clock skew tolerance = %s)' % 
582                   (SAMLDateTime.toString(utcNow),
583                    assertion.conditions.notBefore,
584                    self.clockSkewTolerance))
585            log.warning(msg)
586            return False
587           
588        if (utcNow >= 
589            assertion.conditions.notOnOrAfter + self.clockSkewTolerance):
590            msg = ('The current clock time [%s] is on or after the SAML '
591                   'Attribute Response assertion conditions not on or after '
592                   'time [%s] (with clock skew tolerance = %s)' % 
593                   (SAMLDateTime.toString(utcNow),
594                    assertion.conditions.notOnOrAfter,
595                    self.clockSkewTolerance))
596            log.warning(msg)
597            return False
598           
599        return True
600   
601    def __getstate__(self):
602        '''Enable pickling for use with beaker.session'''
603        _dict = super(SAMLCredentialWallet, self).__getstate__()
604       
605        for attrName in SAMLCredentialWallet.__slots__:
606            # Ugly hack to allow for derived classes setting private member
607            # variables
608            if attrName.startswith('__'):
609                attrName = "_SAMLCredentialWallet" + attrName
610               
611            _dict[attrName] = getattr(self, attrName)
612           
613        return _dict
614       
615       
616class CredentialRepositoryError(_CredentialWalletException):   
617    """Exception handling for NDG Credential Repository class."""
618
619
620class CredentialRepository(object):
621    """CredentialWallet's abstract interface class to a Credential Repository.
622    The Credential Repository is abstract store of user currently valid user
623    credentials.  It enables retrieval of attribute certificates from a user's
624    previous session(s)"""
625       
626    def __init__(self, propFilePath=None, dbPPhrase=None, **prop):
627        """Initialise Credential Repository abstract base class.  Derive from
628        this class to define Credentail Repository interface Credential
629        Wallet
630
631        If the connection string or properties file is set a connection
632        will be made
633
634        @type dbPPhrase: string
635        @param dbPPhrase: pass-phrase to database if applicable
636       
637        @type propFilePath: string
638        @param propFilePath: file path to a properties file.  This could
639        contain configuration parameters for the repository e.g.  database
640        connection parameters
641       
642        @type **prop: dict
643        @param **prop: any other keywords required
644        """
645        raise NotImplementedError(
646            self.__init__.__doc__.replace('\n       ',''))
647
648
649    def addUser(self, userId, dn=None):
650        """A new user to Credentials Repository
651       
652        @type userId: string
653        @param userId: userId for new user
654        @type dn: string
655        @param dn: users Distinguished Name (optional)"""
656        raise NotImplementedError(
657            self.addUser.__doc__.replace('\n       ',''))
658
659                           
660    def auditCredentials(self, userId=None, **attCertValidKeys):
661        """Check the attribute certificates held in the repository and delete
662        any that have expired
663
664        @type userId: basestring/list or tuple
665        @param userId: audit credentials for the input user ID or list of IDs
666        @type attCertValidKeys: dict
667        @param **attCertValidKeys: keywords which set how to check the
668        Attribute Certificate e.g. check validity time, XML signature, version
669         etc.  Default is check validity time only - See AttCert class"""
670        raise NotImplementedError(
671            self.auditCredentials.__doc__.replace('\n       ',''))
672
673
674    def getCredentials(self, userId):
675        """Get the list of credentials for a given users DN
676       
677        @type userId: string
678        @param userId: users userId, name or X.509 cert. distinguished name
679        @rtype: list
680        @return: list of Attribute Certificates"""
681        raise NotImplementedError(
682            self.getCredentials.__doc__.replace('\n       ',''))
683
684       
685    def addCredentials(self, userId, attCertList):
686        """Add new attribute certificates for a user.  The user must have
687        been previously registered in the repository
688
689        @type userId: string
690        @param userId: users userId, name or X.509 cert. distinguished name
691        @type attCertList: list
692        @param attCertList: list of attribute certificates"""
693        raise NotImplementedError(
694            self.addCredentials.__doc__.replace('\n       ',''))
695
696
697class NullCredentialRepository(CredentialRepository):
698    """Implementation of Credential Repository interface with empty stubs. 
699    Use this class in the case where no Credential Repository is required"""
700   
701    def __init__(self, propFilePath=None, dbPPhrase=None, **prop):
702        pass
703
704    def addUser(self, userId):
705        pass
706                           
707    def auditCredentials(self, **attCertValidKeys):
708        pass
709
710    def getCredentials(self, userId):
711        return []
712       
713    def addCredentials(self, userId, attCertList):
714        pass
Note: See TracBrowser for help on using the repository browser.