Changeset 6673
- Timestamp:
- 04/03/10 12:07:21 (11 years ago)
- Location:
- TI12-security/trunk/NDGSecurity/python
- Files:
-
- 8 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDGSecurity/python/.pydevproject
r6628 r6673 3 3 4 4 <pydev_project> 5 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property>6 5 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> 6 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property> 7 7 </pydev_project> -
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/msi.py
r6604 r6673 16 16 import traceback 17 17 import warnings 18 from elementtree import ElementTree18 from xml.etree import ElementTree 19 19 20 20 from ndg.security.common.utils import TypedList -
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/xacml/__init__.py
r6643 r6673 3 3 XACML_2_0_XMLNS = "urn:oasis:names:tc:xacml:2.0:policy:schema:os" 4 4 5 __slots__ = ('__xmlns', )5 __slots__ = ('__xmlns', '__reader', '__writer') 6 6 7 7 ELEMENT_LOCAL_NAME = None … … 9 9 def __init__(self): 10 10 self.__xmlns = PolicyComponent.XACML_2_0_XMLNS 11 self.__reader = None 12 self.__writer = None 11 13 12 14 def _getXmlns(self): … … 25 27 def isValidXmlns(self): 26 28 return self.xmlns in PolicyComponent.XMLNS 29 30 def read(self, obj): 31 """Read using callable assinged to reader property""" 32 if self.__reader is None: 33 raise AttributeError('No reader set for %r' % self.__class__) 34 35 self.__reader(self, obj) 36 37 @classmethod 38 def Read(cls, obj): 39 """Construct a new Policy""" 40 xacmlObj = cls() 41 xacmlObj.read(obj) 42 return xacmlObj 27 43 28 44 def write(self, obj): 45 """Read using callable assinged to reader property""" 46 if self.__writer is None: 47 raise AttributeError('No writer set for %r' % self.__class__) 48 49 self.__writer(self, obj) 50 51 29 52 class RequestPropertyBase(PolicyComponent): 30 53 """Base type for Subject, Resource, Action and Environment types""" -
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/credentialwallet.py
r6615 r6673 612 612 613 613 return _dict 614 615 616 class NDGCredentialWallet(CredentialWalletBase):617 """Volatile store of user credentials associated with a user session618 619 @type userX509Cert: string / M2Crypto.X509.X509 /620 ndg.security.common.X509.X509Cert621 @ivar userX509Cert: X.509 certificate for user (property attribute)622 623 @type userPriKey: string / M2Crypto.RSA.RSA624 @ivar userPriKey: private key for user cert (property attribute)625 626 @type issuingX509Cert: string / ndg.security.common.X509.X509Cert627 @ivar issuingX509Cert: X.509 cert for issuer of user cert (property628 attribute)629 630 @type attributeAuthorityURI: string631 @ivar attributeAuthorityURI: URI of Attribute Authority to make632 requests to. Setting this ALSO creates an AttributeAuthorityClient633 instance _attributeAuthorityClnt. - See attributeAuthorityURI property for634 details. (property attribute)635 636 @type attributeAuthority: ndg.security.server.attributeauthority.AttributeAuthority637 @ivar attributeAuthority: Attribute Authority to make requests to.638 attributeAuthorityURI takes precedence over this keyword i.e. if an639 attributeAuthorityURI has been set, then calls are made to the AA web640 service at this location rather to any self.attributeAuthority running641 locally. (property attribute)642 643 @type caCertFilePathList: string (for single file), list or tuple644 @ivar caCertFilePathList: Certificate Authority's certificates - used645 in validation of signed Attribute Certificates and WS-Security646 signatures of incoming messages. If not set here, it must647 be input in call to getAttCert. (property attribute)648 649 @type credentialRepository: instance of CredentialRepository derived650 class651 @ivar credentialRepository: Credential Repository instance. (property652 attribute). If not set, defaults to NullCredentialRepository type - see653 class below...654 655 656 @type mapFromTrustedHosts: bool657 @ivar mapFromTrustedHosts sets behaviour for getAttCert(). If658 set True and authorisation fails with the given Attribute Authority,659 attempt to get authorisation using Attribute Certificates issued by660 other trusted AAs. (property attribute)661 662 @type rtnExtAttCertList: bool663 @ivar rtnExtAttCertList: behaviour for getAttCert(). If True, and664 authorisation fails with the given Attribute Authority, return a list665 of Attribute Certificates from other trusted AAs which could be used666 to obtain a mapped Attribute Certificate on a subsequent authorisation667 attempt. (property attribute)668 669 @type attCertRefreshElapse: float / int670 @ivar attCertRefreshElapse: used by getAttCert to determine671 whether to replace an existing AC in the cache with a fresh one. If672 the existing one has less than attCertRefreshElapse time in seconds673 left before expiry then replace it. (property attribute)674 675 @type wssCfgKw: dict676 @ivar wssCfgKw: keywords to WS-Security SignatureHandler677 used for Credential Wallet's SOAP interface to Attribute Authorities.678 (property attribute)679 680 @type _credentialRepository: ndg.security.common.CredentialRepository or681 derivative682 @ivar _credentialRepository: reference to Credential Repository object.683 An optional non-volatile cache for storage of wallet info which can be684 later restored. (Don't reference directly - see equivalent property685 attribute)686 687 @type _mapFromTrustedHosts: bool688 @ivar _mapFromTrustedHosts: if true, allow a mapped attribute certificate689 to obtained in a getAttCert call. Set false to prevent mappings.690 (Don't reference directly - see equivalent property attribute)691 692 @type _rtnExtAttCertList: bool693 @ivar _rtnExtAttCertList: if true, return a list of external attribute694 certificates from getAttCert call. (Don't reference directly - see695 equivalent property attribute)696 697 @type __dn: ndg.security.common.X509.X500DN698 @ivar __dn: distinguished name from user certificate. (Don't reference699 directly - see equivalent property attribute)700 701 @type _credentials: dict702 @ivar _credentials: Credentials are stored as a dictionary one element per703 attribute certificate held and indexed by certificate issuer name.704 (Don't reference directly - see equivalent property attribute)705 706 @type _caCertFilePathList: basestring, list, tuple or None707 @ivar _caCertFilePathList: file path(s) to CA certificates. If None708 then the input is quietly ignored. See caCertFilePathList property.709 (Don't reference directly - see equivalent property attribute)710 711 @type _userX509Cert: ndg.security.common.X509.X509Cert712 @ivar _userX509Cert: X.509 user certificate instance.713 (Don't reference directly - see equivalent property attribute)714 715 @type _issuingX509Cert: ndg.security.common.X509.X509Cert716 @ivar _issuingX509Cert: X.509 user certificate instance.717 (Don't reference directly - see equivalent property attribute)718 719 @type _userPriKey: M2Crypto.RSA.RSA720 @ivar _userPriKey: Private key used to sign outbound message.721 (Don't reference directly - see equivalent property attribute)722 """723 724 __metaclass__ = _MetaCredentialWallet725 726 # Names that may be set in a properties file727 propertyDefaults = dict(728 userX509Cert=None,729 userX509CertFilePath=None,730 userPriKey=None,731 userPriKeyFilePath=None,732 issuingX509Cert=None,733 issuingX509CertFilePath=None,734 caCertFilePathList=[],735 sslCACertFilePathList=[],736 attributeAuthority=None,737 credentialRepository=None,738 mapFromTrustedHosts=False,739 rtnExtAttCertList=True,740 attCertRefreshElapse=7200741 )742 743 __slots__ = dict(744 _cfg=None,745 _dn=None,746 _userPriKeyPwd=None,747 _attributeAuthorityClnt=None,748 _attributeAuthorityURI=None,749 sslCACertFilePathList=[],750 wssCfgFilePath=None,751 wssCfgSection='DEFAULT',752 wssCfgPrefix='',753 wssCfgKw={}754 )755 __slots__.update(dict([("_" + n, v) for n, v in propertyDefaults.items()]))756 del n757 758 FUTURE_DEPRECATION_MSG = (759 "This class will be deprecated in future releases. Use "760 "SAMLCredentialWallet and "761 "ndg.security.common.saml_utils.binding.soap.attributequery."762 "AttributeQuerySslSOAPbinding client interface instead for retrieving "763 "and caching user attributes.")764 765 def __init__(self,766 cfg=None,767 cfgFileSection='DEFAULT',768 cfgPrefix='',769 wssCfgKw={},770 **kw):771 """Create store of user credentials for their current session772 773 @type cfg: string / ConfigParser object774 @param cfg: if a string type, this is interpreted as the file path to775 a configuration file, otherwise it will be treated as a ConfigParser776 object777 @type cfgSection: string778 @param cfgSection: sets the section name to retrieve config params779 from780 @type cfgPrefix: basestring781 @param cfgPrefix: apply a prefix to all NDGCredentialWallet config782 params so that if placed in a file with other parameters they can be783 distinguished784 @type cfgKw: dict785 @param cfgKw: set parameters as key value pairs."""786 787 warnings.warn(NDGCredentialWallet.FUTURE_DEPRECATION_MSG)788 log.warning(NDGCredentialWallet.FUTURE_DEPRECATION_MSG)789 log.debug("Calling NDGCredentialWallet.__init__ ...")790 791 super(NDGCredentialWallet, self).__init__()792 793 # Initialise attributes794 for k, v in NDGCredentialWallet.__slots__.items():795 setattr(self, k, v)796 797 # Update attributes from a config file798 if cfg:799 self.parseConfig(cfg, section=cfgFileSection, prefix=cfgPrefix)800 801 # Update attributes from keywords passed - set user private key802 # password first if it's present. This is to avoid an error setting803 # the private key804 self.userPriKeyPwd = kw.pop('userPriKeyPwd', None)805 for k, v in kw.items():806 setattr(self, k, v)807 808 # Get the distinguished name from the user certificate809 if self._userX509Cert:810 self._dn = self._userX509Cert.dn.serialise()811 812 # Make a connection to the Credentials Repository813 if self._credentialRepository is None:814 log.info('Applying default CredentialRepository %r for user '815 '"%s"' % (NullCredentialRepository, self.userId))816 self._credentialRepository = NullCredentialRepository()817 else:818 log.info('Checking CredentialRepository for credentials for user '819 '"%s"' % self.userId)820 821 if not issubclass(self._credentialRepository, CredentialRepository):822 raise CredentialWalletError("Input Credential Repository "823 "instance must be of a class "824 "derived from "825 "\"CredentialRepository\"")826 827 828 # Check for valid attribute certificates for the user829 try:830 self._credentialRepository.auditCredentials(self.userId)831 userCred=self._credentialRepository.getCredentials(self.userId)832 833 except Exception, e:834 log.error("Error updating wallet with credentials from "835 "repository: %s" % e)836 raise837 838 839 # Update wallet with attribute certificates stored in the840 # repository. Store ID and certificate instantiated as an AttCert841 # type842 try:843 for cred in userCred:844 attCert = AttCert.Parse(cred.attCert)845 issuerName = attCert['issuerName']846 847 self.credentials[issuerName] = {'id':cred.id,848 'attCert':attCert}849 except Exception, e:850 try:851 raise CredentialWalletError("Error parsing Attribute "852 "Certificate ID '%s' retrieved from the "853 "Credentials Repository: %s" % (cred.id, e))854 except:855 raise CredentialWalletError("Error parsing Attribute "856 "Certificate retrieved from the "857 "Credentials Repository: %s:" % e)858 859 # Filter out expired or otherwise invalid certificates860 self.audit()861 862 def __getstate__(self):863 '''Enable pickling for use with beaker.session'''864 _dict = super(NDGCredentialWallet, self).__getstate__()865 866 for attrName in NDGCredentialWallet.__slots__:867 # Ugly hack to allow for derived classes setting private member868 # variables869 if attrName.startswith('__'):870 attrName = "_NDGCredentialWallet" + attrName871 872 _dict[attrName] = getattr(self, attrName)873 874 return _dict875 876 def parseConfig(self, cfg, prefix='', section='DEFAULT'):877 '''Extract parameters from cfg config object'''878 879 if isinstance(cfg, basestring):880 cfgFilePath = os.path.expandvars(cfg)881 self._cfg = None882 else:883 cfgFilePath = None884 self._cfg = cfg885 886 # Configuration file properties are held together in a dictionary887 readAndValidate = INIPropertyFileWithValidation()888 prop = readAndValidate(cfgFilePath,889 cfg=self._cfg,890 validKeys=NDGCredentialWallet.propertyDefaults,891 prefix=prefix,892 sections=(section,))893 894 # Keep a copy of config for use by WS-Security SignatureHandler parser895 if self._cfg is None:896 self._cfg = readAndValidate.cfg897 898 # Copy prop dict into object attributes - __slots__ definition and899 # property methods will ensure only the correct attributes are set900 # Set user private key password first if it's present. This is to901 # avoid an error setting the private key902 self.userPriKeyPwd = prop.pop('userPriKeyPwd', None)903 for key, val in prop.items():904 setattr(self, key, val)905 906 907 def _getAttCertRefreshElapse(self):908 """Get property method for Attribute Certificate wallet refresh time909 @rtype: float or int910 @return: "elapse time in seconds"""911 return self._attCertRefreshElapse912 913 def _setAttCertRefreshElapse(self, val):914 """Set property method for Attribute Certificate wallet refresh time915 @type val: float or int916 @param val: "elapse time in seconds"""917 if isinstance(val, (float, int)):918 self._attCertRefreshElapse = val919 920 elif isinstance(val, basestring):921 self._attCertRefreshElapse = float(val)922 else:923 raise AttributeError("Expecting int, float or string type input "924 "for attCertRefreshElapse")925 926 attCertRefreshElapse = property(fget=_getAttCertRefreshElapse,927 fset=_setAttCertRefreshElapse,928 doc="If an existing one has AC less than "929 "attCertRefreshElapse time in seconds "930 "left before expiry then replace it")931 932 def _setX509Cert(self, cert):933 """filter and convert input cert to signing verifying cert set934 property methods. For signingCert, set to None if it is not to be935 included in the SOAP header. For verifyingCert, set to None if this936 cert can be expected to be retrieved from the SOAP header of the937 message to be verified938 939 @type: ndg.security.common.X509.X509Cert / M2Crypto.X509.X509 /940 string or None941 @param cert: X.509 certificate.942 943 @rtype ndg.security.common.X509.X509Cert944 @return X.509 certificate object"""945 946 if cert is None or isinstance(cert, X509Cert):947 # ndg.security.common.X509.X509Cert type / None948 return cert949 950 elif isinstance(cert, X509.X509):951 # M2Crypto.X509.X509 type952 return X509Cert(m2CryptoX509=cert)953 954 elif isinstance(cert, basestring):955 return X509Cert.Parse(cert)956 957 else:958 raise AttributeError("X.509 Cert. must be type: "959 "ndg.security.common.X509.X509Cert, "960 "M2Crypto.X509.X509 or a base64 encoded "961 "string")962 963 def _setUserX509Cert(self, userX509Cert):964 "Set property method for X.509 user cert."965 self._userX509Cert = self._setX509Cert(userX509Cert)966 967 def _getUserX509Cert(self):968 """Get user cert X509Cert instance"""969 return self._userX509Cert970 971 userX509Cert = property(fget=_getUserX509Cert,972 fset=_setUserX509Cert,973 doc="X.509 user certificate instance")974 975 def _setUserX509CertFilePath(self, filePath):976 "Set user X.509 cert file path property method"977 978 if isinstance(filePath, basestring):979 filePath = os.path.expandvars(filePath)980 self._userX509Cert = X509Cert.Read(filePath)981 982 elif filePath is not None:983 raise AttributeError("User X.509 cert. file path must be a valid "984 "string")985 986 self._userX509CertFilePath = filePath987 988 userX509CertFilePath = property(fset=_setUserX509CertFilePath,989 doc="File path to user X.509 cert.")990 991 def _setIssuingX509Cert(self, issuingX509Cert):992 "Set property method for X.509 user cert."993 self._issuingX509Cert = self._setX509Cert(issuingX509Cert)994 995 def _getIssuingX509Cert(self):996 """Get user cert X509Cert instance"""997 return self._issuingX509Cert998 999 issuingX509Cert = property(fget=_getIssuingX509Cert,1000 fset=_setIssuingX509Cert,1001 doc="X.509 user certificate instance")1002 1003 def _setIssuerX509CertFilePath(self, filePath):1004 "Set user X.509 cert file path property method"1005 1006 if isinstance(filePath, basestring):1007 filePath = os.path.expandvars(filePath)1008 self._issuerX509Cert = X509Cert.Read(filePath)1009 1010 elif filePath is not None:1011 raise AttributeError("User X.509 cert. file path must be a valid "1012 "string")1013 1014 self._issuerX509CertFilePath = filePath1015 1016 issuerX509CertFilePath = property(fset=_setIssuerX509CertFilePath,1017 doc="File path to user X.509 cert. "1018 "issuing cert.")1019 1020 def _getUserPriKey(self):1021 "Get method for user private key"1022 return self._userPriKey1023 1024 def _setUserPriKey(self, userPriKey):1025 """Set method for user private key1026 1027 Nb. if input is a string, userPriKeyPwd will need to be set if1028 the key is password protected.1029 1030 @type userPriKey: M2Crypto.RSA.RSA / string1031 @param userPriKey: private key used to sign message"""1032 1033 if userPriKey is None:1034 self._userPriKey = None1035 elif isinstance(userPriKey, basestring):1036 pwdCallback = lambda *ar, **kw: self._userPriKeyPwd1037 self._userPriKey = RSA.load_key_string(userPriKey,1038 callback=pwdCallback)1039 elif isinstance(userPriKey, RSA.RSA):1040 self._userPriKey = userPriKey1041 else:1042 raise AttributeError("user private key must be a valid "1043 "M2Crypto.RSA.RSA type or a string")1044 1045 userPriKey = property(fget=_getUserPriKey,1046 fset=_setUserPriKey,1047 doc="User private key if set, used to sign outbound "1048 "messages to Attribute authority")1049 1050 def _setUserPriKeyFilePath(self, filePath):1051 "Set user private key file path property method"1052 1053 if isinstance(filePath, basestring):1054 filePath = os.path.expandvars(filePath)1055 try:1056 # Read Private key to sign with1057 priKeyFile = BIO.File(open(filePath))1058 pwdCallback = lambda *ar, **kw: self._userPriKeyPwd1059 self._userPriKey = RSA.load_key_bio(priKeyFile,1060 callback=pwdCallback)1061 except Exception, e:1062 raise AttributeError("Setting user private key: %s" % e)1063 1064 elif filePath is not None:1065 raise AttributeError("Private key file path must be a valid "1066 "string or None")1067 1068 self._userPriKeyFilePath = filePath1069 1070 userPriKeyFilePath = property(fset=_setUserPriKeyFilePath,1071 doc="File path to user private key")1072 1073 def _setUserPriKeyPwd(self, userPriKeyPwd):1074 "Set method for user private key file password"1075 if userPriKeyPwd is not None and not isinstance(userPriKeyPwd,1076 basestring):1077 raise AttributeError("Signing private key password must be None "1078 "or a valid string")1079 1080 # Explicitly convert to string as M2Crypto OpenSSL wrapper fails with1081 # unicode type1082 self._userPriKeyPwd = str(userPriKeyPwd)1083 1084 def _getUserPriKeyPwd(self):1085 "Get property method for user private key"1086 return self._userPriKeyPwd1087 1088 userPriKeyPwd = property(fset=_setUserPriKeyPwd,1089 fget=_getUserPriKeyPwd,1090 doc="Password protecting user private key file")1091 1092 def _getCACertFilePathList(self):1093 """Get CA cert or certs used to validate AC signatures and signatures1094 of peer SOAP messages.1095 1096 @rtype caCertFilePathList: basestring, list or tuple1097 @return caCertFilePathList: file path(s) to CA certificates."""1098 return self._caCertFilePathList1099 1100 def _setCACertFilePathList(self, caCertFilePathList):1101 """Set CA cert or certs to validate AC signatures, signatures1102 of Attribute Authority SOAP responses and SSL connections where1103 AA SOAP service is run over SSL.1104 1105 @type caCertFilePathList: basestring, list, tuple or None1106 @param caCertFilePathList: file path(s) to CA certificates. If None1107 then the input is quietly ignored."""1108 1109 if isinstance(caCertFilePathList, basestring):1110 self._caCertFilePathList = [caCertFilePathList]1111 1112 elif isinstance(caCertFilePathList, list):1113 self._caCertFilePathList = caCertFilePathList1114 1115 elif isinstance(caCertFilePathList, tuple):1116 self._caCertFilePathList = list(caCertFilePathList)1117 1118 elif caCertFilePathList is not None:1119 raise TypeError('Expecting string/list/tuple or None type for '1120 '"caCertFilePathList"; got %r type' %1121 type(caCertFilePathList))1122 1123 caCertFilePathList = property(fget=_getCACertFilePathList,1124 fset=_setCACertFilePathList,1125 doc="CA Certificates - used for "1126 "verification of AC and SOAP message "1127 "signatures")1128 1129 def _getAttributeAuthorityURI(self):1130 return self._attributeAuthorityURI1131 1132 def _setAttributeAuthorityURI(self, value):1133 """String or None type are allowed - The URI may be set to None to1134 flag that a local Attribute Authority instance is being invoked rather1135 one hosted via a remote URI1136 """1137 if not isinstance(value, (basestring, type(None))):1138 raise TypeError('Expecting string or None type for '1139 '"attributeAuthorityURI"; got %r instead' %1140 type(value))1141 1142 self._attributeAuthorityURI = value1143 1144 if value is not None:1145 # Re-initialize local instance1146 self._attributeAuthority = NDGCredentialWallet.propertyDefaults[1147 'attributeAuthority']1148 1149 attributeAuthorityURI = property(fget=_getAttributeAuthorityURI,1150 fset=_setAttributeAuthorityURI,1151 doc="Attribute Authority address - "1152 "setting also sets up "1153 "AttributeAuthorityClient instance!")1154 1155 def _getAttributeAuthority(self):1156 """Get property method for Attribute Authority Web Service client1157 instance. Use attributeAuthorityURI propert to set up1158 attributeAuthorityClnt1159 1160 @rtype attributeAuthority: ndg.security.server.attributeauthority.AttributeAuthority1161 @return attributeAuthority: Attribute Authority instance"""1162 return self._attributeAuthority1163 1164 def _setAttributeAuthority(self, attributeAuthority):1165 """Set property method for Attribute Authority Web Service instance to1166 connect to. This method ALSO RESETS attributeAuthorityURI - the1167 address of a remote Attribute Authority - to None1168 1169 @type attributeAuthority: ndg.security.server.attributeauthority.AttributeAuthority1170 @param attributeAuthority: Attribute Authority instance.1171 """1172 if not isinstance(attributeAuthority, (AttributeAuthority, type(None))):1173 raise AttributeError("Expecting %r or None type for "1174 "\"attributeAuthority\" attribute; got %r" %1175 (AttributeAuthority, type(attributeAuthority)))1176 1177 self._attributeAuthority = attributeAuthority1178 1179 # Re-initialize setting for remote service1180 self.attributeAuthorityURI = None1181 1182 attributeAuthority = property(fget=_getAttributeAuthority,1183 fset=_setAttributeAuthority,1184 doc="Attribute Authority instance")1185 1186 1187 def _getMapFromTrustedHosts(self):1188 """Get property method for boolean flag - if set to True it allows1189 role mapping to be attempted when connecting to an Attribute Authority1190 1191 @type mapFromTrustedHosts: bool1192 @param mapFromTrustedHosts: set to True to try role mapping in AC1193 requests to Attribute Authorities"""1194 return self._mapFromTrustedHosts1195 1196 def _setMapFromTrustedHosts(self, mapFromTrustedHosts):1197 """Set property method for boolean flag - if set to True it allows1198 role mapping to be attempted when connecting to an Attribute Authority1199 1200 @type mapFromTrustedHosts: bool1201 @param mapFromTrustedHosts: Attribute Authority Web Service."""1202 if not isinstance(mapFromTrustedHosts, bool):1203 raise AttributeError("Expecting %r for mapFromTrustedHosts "1204 "attribute" % bool)1205 1206 self._mapFromTrustedHosts = mapFromTrustedHosts1207 1208 mapFromTrustedHosts = property(fget=_getMapFromTrustedHosts,1209 fset=_setMapFromTrustedHosts,1210 doc="Set to True to enable mapped AC "1211 "requests")1212 1213 def _getRtnExtAttCertList(self):1214 """Get property method for Attribute Authority Web Service client1215 instance. Use rtnExtAttCertListURI propert to set up1216 rtnExtAttCertListClnt1217 1218 @type rtnExtAttCertList: bool1219 @param rtnExtAttCertList: """1220 return self._rtnExtAttCertList1221 1222 def _setRtnExtAttCertList(self, rtnExtAttCertList):1223 """Set property method for boolean flag - when a AC request fails,1224 return a list of candidate ACs that could be used to re-try with in1225 order to get mapped AC.1226 1227 @type rtnExtAttCertList: bool1228 @param rtnExtAttCertList: set to True to configure getAttCert to return1229 a list of ACs that could be used in a re-try to get a mapped AC from1230 the target Attribute Authority."""1231 if not isinstance(rtnExtAttCertList, bool):1232 raise AttributeError("Expecting %r for rtnExtAttCertList "1233 "attribute" % bool)1234 1235 self._rtnExtAttCertList = rtnExtAttCertList1236 1237 rtnExtAttCertList = property(fget=_getRtnExtAttCertList,1238 fset=_setRtnExtAttCertList,1239 doc="Set to True to enable mapped AC "1240 "requests")1241 1242 def isValid(self, **x509CertKeys):1243 """Check wallet's user cert. If expired return False1244 1245 @type **x509CertKeys: dict1246 @param **x509CertKeys: keywords applying to1247 ndg.security.common.X509.X509Cert.isValidTime method"""1248 if self._userX509Cert is not None:1249 return self._userX509Cert.isValidTime(**x509CertKeys)1250 else:1251 log.warning("NDGCredentialWallet.isValid: no user certificate set in "1252 "wallet")1253 return True1254 1255 def addCredential(self,1256 attCert,1257 attributeAuthorityURI=None,1258 bUpdateCredentialRepository=True):1259 """Add a new attribute certificate to the list of credentials held.1260 1261 @type attCert:1262 @param attCert: new attribute Certificate to be added1263 @type attributeAuthorityURI: basestring1264 @param attributeAuthorityURI: input the Attribute Authority URI from1265 which attCert was retrieved. This is added to a dict to enable access1266 to a given Attribute Certificate keyed by Attribute Authority URI.1267 See the getCredential method.1268 @type bUpdateCredentialRepository: bool1269 @param bUpdateCredentialRepository: if set to True, and a repository1270 exists it will be updated with the new credentials also1271 1272 @rtype: bool1273 @return: True if certificate was added otherwise False. - If an1274 existing certificate from the same issuer has a later expiry it will1275 take precedence and the new input certificate is ignored."""1276 1277 # Check input1278 if not isinstance(attCert, AttCert):1279 raise CredentialWalletError("Credential must be an %r type object" %1280 AttCert)1281 1282 # Check certificate validity1283 try:1284 attCert.isValid(raiseExcep=True)1285 1286 except AttCertError, e:1287 raise CredentialWalletError("Adding Credential: %s" % e)1288 1289 # Check to see if there is an existing Attribute Certificate held1290 # that was issued by the same host. If so, compare the expiry time.1291 # The one with the latest expiry will be retained and the other1292 # ingored1293 bUpdateCred = True1294 issuerName = attCert['issuerName']1295 1296 if issuerName in self.credentials:1297 # There is an existing certificate held with the same issuing1298 # host name as the new certificate1299 attCertOld = self.credentials[issuerName].credential1300 1301 # Get expiry times in datetime format to allow comparison1302 dtAttCertOldNotAfter = attCertOld.getValidityNotAfter(\1303 asDatetime=True)1304 dtAttCertNotAfter = attCert.getValidityNotAfter(asDatetime=True)1305 1306 # If the new certificate has an earlier expiry time then ignore it1307 bUpdateCred = dtAttCertNotAfter > dtAttCertOldNotAfter1308 1309 1310 if bUpdateCred:1311 thisCredential = CredentialContainer(AttCert)1312 thisCredential.credential = attCert1313 thisCredential.issuerName = issuerName1314 thisCredential.attributeAuthorityURI = attributeAuthorityURI1315 1316 self.credentials[issuerName] = thisCredential1317 1318 if attributeAuthorityURI:1319 self.credentialsKeyedByURI[1320 attributeAuthorityURI] = thisCredential1321 1322 # Update the Credentials Repository - the permanent store of user1323 # authorisation credentials. This allows credentials for previous1324 # sessions to be re-instated1325 if self._credentialRepository and bUpdateCredentialRepository:1326 self.updateCredentialRepository()1327 1328 # Flag to caller to indicate whether the input certificate was added1329 # to the credentials or an exsiting certificate from the same issuer1330 # took precedence1331 return bUpdateCred1332 1333 1334 def audit(self):1335 """Check the credentials held in the wallet removing any that have1336 expired or are otherwise invalid."""1337 1338 log.debug("NDGCredentialWallet.audit ...")1339 1340 # Nb. No signature check is carried out. To do a check, access is1341 # needed to the cert of the CA that issued the Attribute Authority's1342 # cert1343 #1344 # P J Kershaw 12/09/051345 for key, val in self.credentials.items():1346 if not val.credential.isValid(chkSig=False):1347 del self.credentials[key]1348 1349 def updateCredentialRepository(self, auditCred=True):1350 """Copy over non-persistent credentials held by wallet into the1351 perminent repository.1352 1353 @type auditCred: bool1354 @param auditCred: filter existing credentials in the repository1355 removing invalid ones"""1356 1357 log.debug("NDGCredentialWallet.updateCredentialRepository ...")1358 1359 if not self._credentialRepository:1360 raise CredentialWalletError("No Credential Repository has been "1361 "created for this wallet")1362 1363 # Filter out invalid certs unless auditCred flag is explicitly set to1364 # false1365 if auditCred: self.audit()1366 1367 # Update the database - only add new entries i.e. with an ID of -11368 attCertList = [i.credential for i in self.credentials.values()1369 if i.id == -1]1370 1371 self._credentialRepository.addCredentials(self.userId, attCertList)1372 1373 def _createAttributeAuthorityClnt(self, attributeAuthorityURI):1374 """Set up a client to an Attribute Authority with the given URI1375 1376 @type attributeAuthorityURI: string1377 @param attributeAuthorityURI: Attribute Authority Web Service URI.1378 1379 @rtype: ndg.security.common.attributeauthority.AttributeAuthorityClient1380 @return: new Attribute Authority client instance"""1381 1382 log.debug('NDGCredentialWallet._createAttributeAuthorityClnt for '1383 'service: "%s"' % attributeAuthorityURI)1384 1385 attributeAuthorityClnt = AttributeAuthorityClient(1386 uri=attributeAuthorityURI,1387 sslCACertFilePathList=self.sslCACertFilePathList,1388 cfg=self.wssCfgFilePath or self._cfg,1389 cfgFileSection=self.wssCfgSection,1390 cfgFilePrefix=self.wssCfgPrefix,1391 **(self.wssCfgKw or {}))1392 1393 # If a user certificate is set, use this to sign messages instead of1394 # the default settings in the WS-Security config.1395 if attributeAuthorityClnt.signatureHandler is not None and \1396 self.userPriKey is not None:1397 if self.issuingX509Cert is not None:1398 # Pass a chain of certificates -1399 # Initialise WS-Security signature handling to pass1400 # BinarySecurityToken containing user cert and cert for user1401 # cert issuer1402 attributeAuthorityClnt.signatureHandler.reqBinSecTokValType = \1403 SignatureHandler.binSecTokValType["X509PKIPathv1"]1404 attributeAuthorityClnt.signatureHandler.signingCertChain = (1405 self.issuingX509Cert, self.userX509Cert)1406 1407 attributeAuthorityClnt.signatureHandler.signingPriKey = \1408 self.userPriKey1409 elif self.userX509Cert is not None:1410 # Pass user cert only - no need to pass a cert chain.1411 # This type of token is more likely to be supported by the1412 # various WS-Security toolkits1413 attributeAuthorityClnt.signatureHandler.reqBinSecTokValType = \1414 SignatureHandler.binSecTokValType["X509v3"]1415 attributeAuthorityClnt.signatureHandler.signingCert = \1416 self.userX509Cert1417 1418 attributeAuthorityClnt.signatureHandler.signingPriKey = \1419 self.userPriKey1420 1421 return attributeAuthorityClnt1422 1423 1424 def _getAttCert(self,1425 attributeAuthorityURI=None,1426 attributeAuthority=None,1427 extAttCert=None):1428 """Wrapper to Attribute Authority attribute certificate request. See1429 getAttCert for the classes' public interface.1430 1431 If successful, a new attribute certificate is issued to the user1432 and added into the wallet1433 1434 @type attributeAuthorityURI: string1435 @param attributeAuthorityURI: to call as a web service, specify the URI1436 for the Attribute Authority.1437 1438 @type attributeAuthority: ndg.security.server.attributeauthority.AttributeAuthority1439 @param attributeAuthority: Alternative to attributeAuthorityURI - to1440 run on the local machine, specify a local Attribute Authority1441 instance.1442 1443 @type extAttCert: ndg.security.common.AttCert.AttCert1444 @param extAttCert: an existing Attribute Certificate which can1445 be used to making a mapping should the user not be registered with the1446 Attribute Authority"""1447 1448 log.debug("NDGCredentialWallet._getAttCert ...")1449 1450 1451 # If a user cert. is present, ignore the user ID setting. The1452 # Attribute Authority will set the userId field of the1453 # Attribute Certificate based on the DN of the user certificate1454 if self.userX509Cert:1455 userId = str(self.userX509Cert.dn)1456 else:1457 userId = self.userId1458 1459 if attributeAuthority is not None and \1460 attributeAuthorityURI is not None:1461 raise KeyError("Both attributeAuthorityURI and attributeAuthority "1462 "keywords have been set")1463 1464 if attributeAuthority is None:1465 attributeAuthority = self.attributeAuthority1466 1467 if attributeAuthorityURI is None:1468 attributeAuthorityURI = self.attributeAuthorityURI1469 1470 # Set a client alias according to whether the Attribute Authority is1471 # being called locally or as a remote service1472 if attributeAuthorityURI is not None:1473 # Call Remote Service at given URI1474 aaInterface = self._createAttributeAuthorityClnt(1475 attributeAuthorityURI)1476 log.debug('NDGCredentialWallet._getAttCert for remote Attribute '1477 'Authority service: "%s" ...' % attributeAuthorityURI)1478 1479 elif attributeAuthority is not None:1480 # Call local based Attribute Authority with settings from the1481 # configuration file attributeAuthority1482 aaInterface = attributeAuthority1483 log.debug('NDGCredentialWallet._getAttCert for local Attribute '1484 'Authority: "%r" ...' % attributeAuthority)1485 else:1486 raise CredentialWalletError("Error requesting attribute: "1487 "certificate a URI or Attribute "1488 "Authority instance must be specified")1489 1490 try:1491 # Request a new attribute certificate from the Attribute1492 # Authority1493 attCert = aaInterface.getAttCert(userId=userId,1494 userAttCert=extAttCert)1495 1496 log.info('Granted Attribute Certificate from issuer DN = "%s"'%1497 attCert.issuerDN)1498 1499 except (AttributeAuthorityAccessDenied, AttributeRequestDenied), e:1500 # AttributeAuthorityAccessDenied is raised if1501 # aaInterface is a local AA instance and1502 # AttributeRequestDenied is raised for a client to a remote AA1503 # service1504 raise CredentialWalletAttributeRequestDenied(str(e))1505 1506 except Exception, e:1507 raise CredentialWalletError("Requesting attribute certificate: %s"%1508 e)1509 1510 # Update attribute Certificate instance with CA's certificate ready1511 # for signature check in addCredential()1512 if self._caCertFilePathList is None:1513 raise CredentialWalletError("No CA certificate has been set")1514 1515 attCert.certFilePathList = self._caCertFilePathList1516 1517 1518 # Add credential into wallet1519 #1520 # Nb. if the certificates signature is invalid, it will be rejected1521 log.debug("Adding credentials into wallet...")1522 self.addCredential(attCert)1523 1524 return attCert1525 1526 def _getAAHostInfo(self,1527 attributeAuthority=None,1528 attributeAuthorityURI=None):1529 """Wrapper to Attribute Authority getHostInfo1530 1531 _getAAHostInfo([attributeAuthority=f|attributeAuthorityURI=u])1532 1533 @type userRole: string1534 @param userRole: get hosts which have a mapping to this role1535 1536 @type attributeAuthorityURI: string1537 @param attributeAuthorityURI: to call as a web service, specify the URI1538 for the Attribute Authority.1539 1540 @type attributeAuthority: string1541 @param attributeAuthority: Alternative to attributeAuthorityURI - to1542 run on the local machine, specify the local Attribute Authority1543 instance.1544 """1545 1546 if attributeAuthority is None:1547 attributeAuthority = self.attributeAuthority1548 1549 if attributeAuthorityURI is None:1550 attributeAuthorityURI = self.attributeAuthorityURI1551 1552 log.debug('NDGCredentialWallet._getAAHostInfo for service: "%s" ...' %1553 attributeAuthorityURI or attributeAuthority)1554 1555 # Set a client alias according to whether the Attribute Authority is1556 # being called locally or asa remote service1557 if attributeAuthorityURI is not None:1558 # Call Remote Service at given URI1559 attributeAuthorityClnt = self._createAttributeAuthorityClnt(1560 attributeAuthorityURI)1561 1562 elif attributeAuthority is not None:1563 # Call local based Attribute Authority with settings from the1564 # configuration file attributeAuthority1565 attributeAuthorityClnt = attributeAuthority1566 1567 else:1568 raise CredentialWalletError("Error requesting trusted hosts info: "1569 "a URI or Attribute Authority "1570 "configuration file must be specified")1571 1572 try:1573 # Request a new attribute certificate from the Attribute1574 # Authority1575 return attributeAuthorityClnt.getHostInfo()1576 1577 except Exception, e:1578 log.error("Requesting host info: %s" % e)1579 raise1580 1581 def _getAATrustedHostInfo(self,1582 userRole=None,1583 attributeAuthority=None,1584 attributeAuthorityURI=None):1585 """Wrapper to Attribute Authority getTrustedHostInfo1586 1587 _getAATrustedHostInfo([userRole=r, ][attributeAuthority=f|1588 attributeAuthorityURI=u])1589 1590 @type userRole: string1591 @param userRole: get hosts which have a mapping to this role1592 1593 @type attributeAuthorityURI: string1594 @param attributeAuthorityURI: to call as a web service, specify the URI1595 for the Attribute Authority.1596 1597 @type attributeAuthority: string1598 @param attributeAuthority: Alternative to attributeAuthorityURI - to1599 run on the local machine, specify the local Attribute Authority1600 instance.1601 """1602 1603 if attributeAuthority is None:1604 attributeAuthority = self.attributeAuthority1605 1606 if attributeAuthorityURI is None:1607 attributeAuthorityURI = self.attributeAuthorityURI1608 1609 log.debug('NDGCredentialWallet._getAATrustedHostInfo for role "%s" and '1610 'service: "%s" ...' % (userRole,1611 attributeAuthorityURI or attributeAuthority))1612 1613 # Set a client alias according to whether the Attribute Authority is1614 # being called locally or asa remote service1615 if attributeAuthorityURI is not None:1616 # Call Remote Service at given URI1617 attributeAuthorityClnt = self._createAttributeAuthorityClnt(1618 attributeAuthorityURI)1619 1620 elif attributeAuthority is not None:1621 # Call local based Attribute Authority with settings from the1622 # configuration file attributeAuthority1623 attributeAuthorityClnt = attributeAuthority1624 1625 else:1626 raise CredentialWalletError("Error requesting trusted hosts info: "1627 "a URI or Attribute Authority "1628 "configuration file must be specified")1629 1630 try:1631 # Request a new attribute certificate from the Attribute1632 # Authority1633 return attributeAuthorityClnt.getTrustedHostInfo(role=userRole)1634 1635 except Exception, e:1636 log.error("Requesting trusted host info: %s" % e)1637 raise1638 1639 def getAttCert(self,1640 reqRole=None,1641 attributeAuthority=None,1642 attributeAuthorityURI=None,1643 mapFromTrustedHosts=None,1644 rtnExtAttCertList=None,1645 extAttCertList=None,1646 extTrustedHostList=None,1647 refreshAttCert=False,1648 attCertRefreshElapse=None):1649 1650 """Get an Attribute Certificate from an Attribute Authority. If this1651 fails try to make a mapped Attribute Certificate by using a certificate1652 from another host which has a trust relationship to the Attribute1653 Authority in question.1654 1655 getAttCert([reqRole=r, ][attributeAuthority=a|attributeAuthorityURI=u,]1656 [mapFromTrustedHosts=m, ]1657 [rtnExtAttCertList=e, ][extAttCertList=el, ]1658 [extTrustedHostList=et, ][refreshAttCert=ra])1659 1660 The procedure is:1661 1662 1) Try attribute request using user certificate1663 2) If the Attribute Authority (AA) doesn't recognise the certificate,1664 find out any other hosts which have a trust relationship to the AA.1665 3) Look for Attribute Certificates held in the wallet corresponding1666 to these hosts.1667 4) If no Attribute Certificates are available, call the relevant1668 hosts' AAs to get certificates1669 5) Finally, use these new certificates to try to obtain a mapped1670 certificate from the original AA1671 6) If this fails access is denied1672 1673 @type reqRole: string1674 @param reqRole: the required role to get access for1675 1676 @type attributeAuthorityURI: string1677 @param attributeAuthorityURI: to call as a web service, specify the URI1678 for the Attribute Authority.1679 1680 @type attributeAuthority: string1681 @param attributeAuthority: Altenrative to attributeAuthorityURI - to1682 run on the local machine, specify a local Attribute Authority1683 instance.1684 1685 @type mapFromTrustedHosts: bool / None1686 @param mapFromTrustedHosts: if request fails via the user's cert1687 ID, then it is possible to get a mapped certificate by using1688 certificates from other AA's. Set this flag to True, to allow this1689 second stage of generating a mapped certificate from the certificate1690 stored in the wallet credentials.1691 1692 If set to False, it is possible to return the list of certificates1693 available for mapping and then choose which one or ones to use for1694 mapping by re-calling getAttCert with extAttCertList set to these1695 certificates.1696 1697 Defaults to None in which case self._mapFromTrustedHosts is not1698 altered1699 1700 The list is returned via CredentialWalletAttributeRequestDenied1701 exception. If no value is set, the default value held in1702 self.mapFromTrustedHosts is used1703 1704 @type rtnExtAttCertList: bool / None1705 @param rtnExtAttCertList: If request fails, make a list of1706 candidate certificates from other Attribute Authorities which the user1707 could use to retry and get a mapped certificate.1708 1709 If mapFromTrustedHosts is set True this flags value is overriden and1710 effectively set to True.1711 1712 If no value is set, the default value held in self._rtnExtAttCertList1713 is used.1714 1715 The list is returned via a CredentialWalletAttributeRequestDenied1716 exception object.1717 1718 @type extAttCertList: list1719 @param extAttCertList: Attribute Certificate or list of certificates1720 from other Attribute Authorities. These can be used to get a mapped1721 certificate if access fails based on the user's certificate1722 credentials. They are tried out in turn until access is granted so1723 the order of the list decides the order in which they will be tried1724 1725 @type extTrustedHostList:1726 @param extTrustedHostList: same as extAttCertList keyword, but1727 instead of providing Attribute Certificates, give a list of Attribute1728 Authority hosts. These will be matched up to Attribute Certificates1729 held in the wallet. Matching certificates will then be used to try to1730 get a mapped Attribute Certificate.1731 1732 @type refreshAttCert: bool1733 @param refreshAttCert: if set to True, the attribute request1734 will go ahead even if the wallet already contains an Attribute1735 Certificate from the target Attribute Authority. The existing AC in1736 the wallet will be replaced by the new one obtained from this call.1737 1738 If set to False, this method will check to see if an AC issued by the1739 target AA already exists in the wallet. If so, it will return this AC1740 to the caller without proceeding to make a call to the AA.1741 1742 @type attCertRefreshElapse: float / int1743 @param attCertRefreshElapse: determine whether to replace an1744 existing AC in the cache with a fresh one. If the existing one has1745 less than attCertRefreshElapse time in seconds left before expiry then1746 replace it.1747 1748 @rtype: ndg.security.common.AttCert.AttCert1749 @return: Attribute Certificate retrieved from Attribute Authority"""1750 1751 log.debug("NDGCredentialWallet.getAttCert ...")1752 1753 # Both these assignments are calling set property methods implicitly!1754 if attributeAuthorityURI:1755 self.attributeAuthorityURI = attributeAuthorityURI1756 1757 if attributeAuthority is not None:1758 self.attributeAuthority = attributeAuthority1759 1760 if not refreshAttCert and self.credentials:1761 # Refresh flag is not set so it's OK to check for any existing1762 # Attribute Certificate in the wallet whose issuerName match the1763 # target AA's name1764 1765 # Find out the site ID for the target AA by calling AA's host1766 # info WS method1767 log.debug("NDGCredentialWallet.getAttCert - check AA site ID ...")1768 try:1769 hostInfo = self._getAAHostInfo()1770 aaName = hostInfo.keys()[0]1771 except Exception, e:1772 raise CredentialWalletError("Getting host info: %s" % e)1773 1774 # Look in the wallet for an AC with the same issuer name1775 if aaName in self.credentials:1776 # Existing Attribute Certificate found in wallet - Check that1777 # it will be valid for at least the next 2 hours1778 if attCertRefreshElapse is not None:1779 self.attCertRefreshElapse = attCertRefreshElapse1780 1781 dtNow = datetime.utcnow() + \1782 timedelta(seconds=self.attCertRefreshElapse)1783 1784 attCert = self.credentials[aaName]['attCert']1785 if attCert.isValidTime(dtNow=dtNow):1786 log.info("Retrieved an existing %s AC from the wallet" %1787 aaName)1788 return attCert1789 1790 # Check for settings from input, if not set use previous settings1791 # made1792 if mapFromTrustedHosts is not None:1793 self.mapFromTrustedHosts = mapFromTrustedHosts1794 1795 if rtnExtAttCertList is not None:1796 self.rtnExtAttCertList = rtnExtAttCertList1797 1798 # Check for list of external trusted hosts (other trusted NDG data1799 # centres)1800 if extTrustedHostList:1801 log.info("Checking for ACs in wallet matching list of trusted "1802 "hosts set: %s" % extTrustedHostList)1803 1804 if not self.mapFromTrustedHosts:1805 raise CredentialWalletError("A list of trusted hosts has been "1806 "input but mapping from trusted hosts "1807 "is set to disallowed")1808 1809 if isinstance(extTrustedHostList, basestring):1810 extTrustedHostList = [extTrustedHostList]1811 1812 # Nb. Any extAttCertList is overriden by extTrustedHostList being1813 # set1814 extAttCertList = [self.credentials[hostName]['attCert']1815 for hostName in extTrustedHostList1816 if hostName in self.credentials]1817 1818 # Set an empty list to trigger an AttributeError by initialising it to1819 # None1820 if extAttCertList == []:1821 extAttCertList = None1822 1823 # Repeat authorisation attempts until succeed or means are exhausted1824 while True:1825 1826 # Check for candidate certificates for mapping1827 try:1828 # If list is set get the next cert1829 extAttCert = extAttCertList.pop()1830 1831 except AttributeError:1832 log.debug("No external Attribute Certificates - trying "1833 "request without mapping...")1834 # No List set - attempt request without1835 # using mapping from trusted hosts1836 extAttCert = None1837 1838 except IndexError:1839 1840 # List has been emptied without attribute request succeeding -1841 # give up1842 errMsg = ("Attempting to obtained a mapped certificate: "1843 "no external attribute certificates are available")1844 1845 # Add the exception form the last call to the Attribute1846 # Authority if an error exists1847 try:1848 errMsg += ": %s" % attributeRequestDenied1849 except NameError:1850 pass1851 1852 raise CredentialWalletAttributeRequestDenied(errMsg)1853 1854 1855 # Request Attribute Certificate from Attribute Authority1856 try:1857 attCert = self._getAttCert(extAttCert=extAttCert)1858 # Access granted1859 return attCert1860 1861 except CredentialWalletAttributeRequestDenied, \1862 attributeRequestDenied:1863 if not self.mapFromTrustedHosts and not self.rtnExtAttCertList:1864 log.debug("Creating a mapped certificate option is not "1865 "set - raising "1866 "CredentialWalletAttributeRequestDenied "1867 "exception saved from earlier")1868 raise attributeRequestDenied1869 1870 if isinstance(extAttCertList, list):1871 # An list of attribute certificates from trusted hosts1872 # is present continue cycling through this until one of1873 # them is accepted and a mapped certificate can be derived1874 log.debug("AC request denied - but external ACs available "1875 "to try mapped AC request ...")1876 continue1877 1878 # Use the input required role and the AA's trusted host list1879 # to identify attribute certificates from other hosts which1880 # could be used to make a mapped certificate1881 log.debug("Getting a list of trusted hosts for mapped AC "1882 "request ...")1883 try:1884 trustedHostInfo = self._getAATrustedHostInfo(reqRole)1885 1886 except NoMatchingRoleInTrustedHosts, e:1887 raise CredentialWalletAttributeRequestDenied(1888 'Can\'t get a mapped Attribute Certificate for '1889 'the "%s" role' % reqRole)1890 1891 except Exception, e:1892 raise CredentialWalletError("Getting trusted hosts: %s"%e)1893 1894 if not trustedHostInfo:1895 raise CredentialWalletAttributeRequestDenied(1896 "Attribute Authority has no trusted hosts with "1897 "which to make a mapping")1898 1899 # Initialise external certificate list here - if none are1900 # found IndexError will be raised on the next iteration and1901 # an access denied error will be raised1902 extAttCertList = []1903 1904 # Look for Attribute Certificates with matching issuer host1905 # names1906 log.debug("Checking wallet for ACs issued by one of the "1907 "trusted hosts...")1908 for hostName in self.credentials:1909 1910 # Nb. Candidate certificates for mappings must have1911 # original provenance and contain at least one of the1912 # required roles1913 attCert = self.credentials[hostName].credential1914 1915 if hostName in trustedHostInfo and attCert.isOriginal():1916 for role in attCert.roles:1917 if role in trustedHostInfo[hostName]['role']:1918 extAttCertList.append(attCert)1919 1920 if not extAttCertList:1921 log.debug("No wallet ACs matched any of the trusted "1922 "hosts. - Try request for an AC from a "1923 "trusted host ...")1924 1925 # No certificates in the wallet matched the trusted host1926 # and required roles1927 #1928 # Try each host in turn in order to get a certificate with1929 # the required credentials in order to do a mapping1930 for host, info in trustedHostInfo.items():1931 try:1932 # Try request to trusted host1933 extAttCert = self._getAttCert(1934 attributeAuthorityURI=info['aaURI'])1935 1936 # Check the certificate contains at least one of1937 # the required roles1938 if [True for r in extAttCert.roles1939 if r in info['role']]:1940 extAttCertList.append(extAttCert)1941 1942 # For efficiency, stop once obtained a valid1943 # cert - but may want complete list for user to1944 # choose from1945 #break1946 1947 except Exception, e:1948 # ignore any errors and continue1949 log.warning('AC request to trusted host "%s"'1950 ' resulted in: %s' % (info['aaURI'],e))1951 1952 if not extAttCertList:1953 raise CredentialWalletAttributeRequestDenied(1954 "No certificates are available with which to "1955 "make a mapping to the Attribute Authority")1956 1957 1958 if not self.mapFromTrustedHosts:1959 1960 # Exit here returning the list of candidate certificates1961 # that could be used to make a mapped certificate1962 msg = ("User is not registered with Attribute "1963 "Authority - retry using one of the returned "1964 "Attribute Certificates obtained from other "1965 "trusted hosts")1966 1967 raise CredentialWalletAttributeRequestDenied(msg,1968 extAttCertList=extAttCertList,1969 trustedHostInfo=trustedHostInfo)1970 614 1971 615 -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/attributeauthority.py
r6615 r6673 29 29 30 30 from ndg.saml.utils import SAMLDateTime 31 from ndg.saml.saml2.core import (Response, Assertion, Attribute, AttributeStatement, 32 SAMLVersion, Subject, NameID, Issuer, Conditions, 33 AttributeQuery, XSStringAttributeValue, Status, 34 StatusCode, StatusMessage) 31 from ndg.saml.saml2.core import (Response, Assertion, Attribute, 32 AttributeStatement, SAMLVersion, Subject, 33 NameID, Issuer, Conditions, AttributeQuery, 34 XSStringAttributeValue, Status, 35 StatusCode, StatusMessage) 35 36 36 37 from ndg.security.common.saml_utils.esg import EsgSamlNamespaces … … 39 40 from ndg.security.common.utils.configfileparsers import ( 40 41 CaseSensitiveConfigParser) 41 42 # X.509 Certificate handling43 from ndg.security.common.X509 import X509Cert, X500DN44 45 # NDG Attribute Certificate46 from ndg.security.common.AttCert import AttCert47 42 48 43 … … 91 86 keywords for the Attribute Interface plugin 92 87 93 @type mapConfigHostDefaults: dict94 @cvar mapConfigHostDefaults: valid configuration property95 keywords for the Map Configuration XML Host element96 97 88 @type DEFAULT_CONFIG_DIRNAME: string 98 89 @cvar DEFAULT_CONFIG_DIRNAME: configuration directory under $NDGSEC_DIR - … … 117 108 DEFAULT_PROPERTY_FILENAME = "attributeAuthority.cfg" 118 109 ATTRIBUTE_INTERFACE_KEYNAME = 'attributeInterface' 119 CONFIG_LIST_SEP_PAT = re.compile(',\ W*')110 CONFIG_LIST_SEP_PAT = re.compile(',\s*') 120 111 121 112 attributeInterfacePropertyDefaults = { … … 130 121 propertyDefaults = { 131 122 'name': '', 132 'signingCertFilePath': '',133 'signingPriKeyFilePath': '',134 'signingPriKeyPwd': None,135 'caCertFilePathList': [],136 123 'attCertLifetime': -1, 137 124 'attCertNotBeforeOff': 0., 138 125 'clockSkew': timedelta(seconds=0.), 139 'attCertFileName': '',140 'attCertFileLogCnt': 0,141 'mapConfigFilePath': '',142 'attCertDir': '',143 126 'dnSeparator': '/', 144 127 ATTRIBUTE_INTERFACE_KEYNAME: attributeInterfacePropertyDefaults … … 167 150 self.__propFileSection = 'DEFAULT' 168 151 self.__propPrefix = '' 169 170 # Initialise role mapping look-ups - These are set in readMapConfig() 171 self.__mapConfig = None 172 self.__localRole2RemoteRole = None 173 self.__remoteRole2LocalRole = None 174 152 175 153 self.__cert = None 176 154 … … 184 162 self.__attributeInterfaceCfg = {} 185 163 186 def _getMapConfig(self):187 return self.__mapConfig188 189 164 def _getCert(self): 190 165 return self.__cert … … 196 171 return self.__issuerSerialNumber 197 172 198 def _getAttCertLog(self):199 return self.__attCertLog200 201 173 def _getName(self): 202 174 return self.__name … … 211 183 return self.__clockSkew 212 184 213 def _getAttCertDir(self):214 return self.__attCertDir215 216 185 def _getAttributeInterface(self): 217 186 return self.__attributeInterface 218 219 def _getTrustedHostInfo(self):220 return self.__trustedHostInfo221 187 222 188 def _setCert(self, value): … … 236 202 self.__issuerSerialNumber = value 237 203 238 def _setAttCertLog(self, value):239 if not isinstance(value, AttCertLog):240 raise TypeError('Expecting %r type for "attCertLog"; got %r' %241 (AttCertLog, type(value)))242 self.__attCertLog = value243 244 204 def _setName(self, value): 245 205 if not isinstance(value, basestring): … … 278 238 '"clockSkew"; got %r' % type(value)) 279 239 280 def _setAttCertDir(self, value):281 if not isinstance(value, basestring):282 raise TypeError('Expecting string type for "attCertDir"; got %r' %283 type(value))284 285 # Check directory path286 try:287 dirList = os.listdir(value)288 289 except OSError, osError:290 raise AttributeAuthorityConfigError('Invalid directory path for '291 'Attribute Certificates store '292 '"%s": %s' %293 (value, osError.strerror))294 self.__attCertDir = value295 296 240 def _setAttributeInterface(self, value): 297 241 if not isinstance(value, AttributeInterface): … … 301 245 302 246 self.__attributeInterface = value 303 304 def _setTrustedHostInfo(self, value):305 self.__trustedHostInfo = value306 247 307 248 def _get_caCertFilePathList(self): … … 324 265 "used to validate an Attribute " 325 266 "Certificate") 326 327 def _get_signingCertFilePath(self):328 return self.__signingCertFilePath329 330 def _set_signingCertFilePath(self, value):331 if not isinstance(value, basestring):332 raise TypeError('Expecting string type for "signingCertFilePath"; '333 'got %r' % type(value))334 self.__signingCertFilePath = value335 336 signingCertFilePath = property(fget=_get_signingCertFilePath,337 fset=_set_signingCertFilePath,338 doc="X.509 certificate used for Attribute "339 "certificate signature")340 341 def _get_signingPriKeyFilePath(self):342 return self.__signingPriKeyFilePath343 344 def _set_signingPriKeyFilePath(self, value):345 if not isinstance(value, basestring):346 raise TypeError('Expecting string type for '347 '"signingPriKeyFilePath"; got %r' % type(value))348 self.__signingPriKeyFilePath = value349 350 signingPriKeyFilePath = property(fget=_get_signingPriKeyFilePath,351 fset=_set_signingPriKeyFilePath,352 doc="File Path for private key used to "353 "sign Attribute certificate")354 355 def _get_signingPriKeyPwd(self):356 return self.__signingPriKeyPwd357 358 def _set_signingPriKeyPwd(self, value):359 if not isinstance(value, (type(None), basestring)):360 raise TypeError('Expecting string or None type for '361 '"signingPriKeyPwd"; got %r' % type(value))362 self.__signingPriKeyPwd = value363 364 signingPriKeyPwd = property(fget=_get_signingPriKeyPwd,365 fset=_set_signingPriKeyPwd,366 doc="Password for private key file used to "367 "for Attribute certificate signature")368 267 369 268 def _get_attributeInterfaceCfg(self): … … 373 272 doc="Settings for Attribute Interface " 374 273 "initialisation") 375 376 def _get_attCertFileName(self):377 return self.__attCertFileName378 379 def _set_attCertFileName(self, value):380 if not isinstance(value, basestring):381 raise TypeError('Expecting string type for "attCertFileName"; got '382 '%r' % type(value))383 384 self.__attCertFileName = value385 386 attCertFileName = property(fget=_get_attCertFileName,387 fset=_set_attCertFileName,388 doc="Attribute certificate file name for log "389 "initialisation")390 391 def _get_attCertFileLogCnt(self):392 return self.__attCertFileLogCnt393 394 def _set_attCertFileLogCnt(self, value):395 if isinstance(value, int):396 self.__attCertFileLogCnt = value397 elif isinstance(value, basestring):398 self.__attCertFileLogCnt = int(value)399 else:400 raise TypeError('Expecting int or string type for '401 '"attCertFileLogCnt"; got %r' % type(value))402 403 attCertFileLogCnt = property(fget=_get_attCertFileLogCnt,404 fset=_set_attCertFileLogCnt,405 doc="Counter for Attribute Certificate log "406 "rotating file handler")407 274 408 275 def _get_dnSeparator(self): … … 419 286 doc="Distinguished Name separator character used " 420 287 "with X.509 Certificate issuer certificate") 421 422 def _getMapConfigFilePath(self):423 return self.__mapConfigFilePath424 425 def _setMapConfigFilePath(self, val):426 if not isinstance(val, basestring):427 raise AttributeAuthorityConfigError("Input Map Configuration "428 "file path must be a "429 "valid string.")430 self.__mapConfigFilePath = val431 432 mapConfigFilePath = property(fget=_getMapConfigFilePath,433 fset=_setMapConfigFilePath,434 doc="File path for Role Mapping "435 "configuration")436 288 437 289 def setPropFilePath(self, val=None): … … 542 394 fget=getPropPrefix, 543 395 doc="Set a prefix for ini file properties") 544 545 mapConfig = property(fget=_getMapConfig,546 doc="MapConfig object")547 396 548 397 cert = property(fget=_getCert, … … 557 406 fset=_setIssuerSerialNumber, 558 407 doc="Issuer Serial Number") 559 560 attCertLog = property(fget=_getAttCertLog,561 fset=_setAttCertLog,562 doc="Attribute certificate logging object")563 408 564 409 name = property(fget=_getName, … … 580 425 " Query issueInstant parameter check") 581 426 582 attCertDir = property(fget=_getAttCertDir,583 fset=_setAttCertDir,584 doc="Attribute certificate log directory")585 586 427 attributeInterface = property(fget=_getAttributeInterface, 587 428 fset=_setAttributeInterface, … … 589 430 590 431 name = property(fget=_getName, fset=_setName, doc="Organisation Name") 591 592 trustedHostInfo = property(fget=_getTrustedHostInfo,593 fset=_setTrustedHostInfo,594 doc="Dictionary of trusted organisations")595 432 596 433 @classmethod … … 630 467 return attributeAuthority 631 468 632 633 469 @classmethod 634 470 def fromProperties(cls, propPrefix='attributeauthority.', … … 697 533 698 534 attCertFilePath = os.path.join(self.attCertDir, self.attCertFileName) 699 700 # Rotating file handler used for logging attribute certificates701 # issued.702 self.attCertLog = AttCertLog(attCertFilePath,703 backUpCnt=self.attCertFileLogCnt)704 535 705 536 def setProperties(self, **prop): … … 774 605 objectType=AttributeInterface, 775 606 classProperties=classProperties) 776 777 def getAttCert(self,778 userId=None,779 holderX509Cert=None,780 holderX509CertFilePath=None,781 userAttCert=None,782 userAttCertFilePath=None):783 784 """Request a new Attribute Certificate for use in authorisation785 786 getAttCert([userId=uid][holderX509Cert=x509Cert|787 holderX509CertFilePath=x509CertFile, ]788 [userAttCert=cert|userAttCertFilePath=certFile])789 790 @type userId: string791 @param userId: identifier for the user who is entitled to the roles792 in the certificate that is issued. If this keyword is omitted, then793 the userId will be set to the DN of the holder.794 795 holder = the holder of the certificate - an inidividual user or an796 organisation to which the user belongs who vouches for that user's ID797 798 userId = the identifier for the user who is entitled to the roles799 specified in the Attribute Certificate that is issued.800 801 @type holderX509Cert: string / ndg.security.common.X509.X509Cert type802 @param holderX509Cert: base64 encoded string containing proxy cert./803 X.509 cert object corresponding to the ID who will be the HOLDER of804 the Attribute Certificate that will be issued. - Normally, using805 proxy certificates, the holder and user ID are the same but there806 may be cases where the holder will be an organisation ID. This is the807 case for NDG security with the DEWS project808 809 @param holderX509CertFilePath: string810 @param holderX509CertFilePath: file path to proxy/X.509 certificate of811 candidate holder812 813 @type userAttCert: string or AttCert type814 @param userAttCert: externally provided attribute certificate from815 another data centre. This is only necessary if the user is not816 registered with this attribute authority.817 818 @type userAttCertFilePath: string819 @param userAttCertFilePath: alternative to userAttCert except pass820 in as a file path to an attribute certificate instead.821 822 @rtype: AttCert823 @return: new attribute certificate"""824 825 log.debug("Calling getAttCert ...")826 827 # Read candidate Attribute Certificate holder's X.509 certificate828 try:829 if holderX509CertFilePath is not None:830 831 # Certificate input as a file832 holderX509Cert = X509Cert()833 holderX509Cert.read(holderX509CertFilePath)834 835 elif isinstance(holderX509Cert, basestring):836 837 # Certificate input as string text838 holderX509Cert = X509Cert.Parse(holderX509Cert)839 840 elif not isinstance(holderX509Cert, (X509Cert, None.__class__)):841 raise AttributeAuthorityError("Holder X.509 Certificate must "842 "be set to valid type: a file "843 "path, string, X509 object or "844 "None")845 except Exception, e:846 log.error("Holder X.509 certificate: %s" % e)847 raise848 849 850 # Check certificate hasn't expired851 if holderX509Cert:852 log.debug("Checking candidate holder X.509 certificate ...")853 try:854 holderX509Cert.isValidTime(raiseExcep=True)855 856 except Exception, e:857 log.error("User X.509 certificate is invalid: " + e)858 raise859 860 861 # If no user ID is input, set id from holder X.509 certificate DN862 # instead863 if not userId:864 if not holderX509Cert:865 raise AttributeAuthorityError("If no user ID is set a holder "866 "X.509 certificate must be "867 "present")868 try:869 userId = holderX509Cert.dn.serialise(\870 separator=self.dnSeparator)871 except Exception, e:872 log.error("Setting user Id from holder certificate DN: %s" % e)873 raise874 875 # Make a new Attribute Certificate instance passing in certificate876 # details for later signing877 attCert = AttCert()878 879 # First certificate in list contains the public key corresponding to880 # the private key881 attCert.certFilePathList = [self.signingCertFilePath] + \882 self.caCertFilePathList883 884 # Check for expiry of each certificate885 for x509Cert in attCert.certFilePathList:886 X509Cert.Read(x509Cert).isValidTime(raiseExcep=True)887 888 attCert.signingKeyFilePath = self.signingPriKeyFilePath889 attCert.signingKeyPwd = self.signingPriKeyPwd890 891 892 # Set holder's Distinguished Name if a holder X.509 certificate was893 # input894 if holderX509Cert:895 try:896 attCert['holder'] = holderX509Cert.dn.serialise(897 separator=self.dnSeparator)898 except Exception, e:899 log.error("Holder X.509 Certificate DN: %s" % e)900 raise901 902 # Set Issuer details from Attribute Authority903 issuerDN = self.cert.dn904 try:905 attCert['issuer'] = \906 issuerDN.serialise(separator=self.dnSeparator)907 except Exception, e:908 log.error("Issuer X.509 Certificate DN: %s" % e)909 raise910 911 attCert['issuerName'] = self.name912 attCert['issuerSerialNumber'] = self.issuerSerialNumber913 914 attCert['userId'] = userId915 916 # Set validity time917 try:918 attCert.setValidityTime(919 lifetime=self.attCertLifetime,920 notBeforeOffset=self.attCertNotBeforeOff)921 922 # Check against the holder X.509 certificate's expiry if set923 if holderX509Cert:924 dtHolderCertNotAfter = holderX509Cert.notAfter925 926 if attCert.getValidityNotAfter(asDatetime=True) > \927 dtHolderCertNotAfter:928 929 # Adjust the attribute certificate's expiry date time930 # so that it agrees with that of the certificate931 # ... but also make ensure that the not before skew is932 # still applied933 attCert.setValidityTime(dtNotAfter=dtHolderCertNotAfter,934 notBeforeOffset=self.attCertNotBeforeOff)935 936 except Exception, e:937 log.error("Error setting attribute certificate validity time: %s" %938 e)939 raise940 941 # Check name is registered with this Attribute Authority - if no942 # user roles are found, the user is not registered943 userRoles = self.getRoles(userId)944 if userRoles:945 # Set as an Original Certificate946 #947 # User roles found - user is registered with this data centre948 # Add roles for this user for this data centre949 attCert.addRoles(userRoles)950 951 # Mark new Attribute Certificate as an original952 attCert['provenance'] = AttCert.origProvenance953 954 else:955 # Set as a Mapped Certificate956 #957 # No roles found - user is not registered with this data centre958 # Check for an externally provided certificate from another959 # trusted data centre960 if userAttCertFilePath:961 962 # Read externally provided certificate963 try:964 userAttCert = AttCert.Read(userAttCertFilePath)965 966 except Exception, e:967 raise AttributeAuthorityError("Reading external Attribute "968 "Certificate: %s" % e)969 elif userAttCert:970 # Allow input as a string but convert to971 if isinstance(userAttCert, basestring):972 userAttCert = AttCert.Parse(userAttCert)973 974 elif not isinstance(userAttCert, AttCert):975 raise AttributeAuthorityError(976 "Expecting userAttCert as a string or AttCert type")977 else:978 raise AttributeAuthorityAccessDenied('User "%s" is not '979 'registered and no external attribute certificate is '980 'available to make a mapping.' % userId)981 982 983 # Check it's an original certificate - mapped certificates can't984 # be used to make further mappings985 if userAttCert.isMapped():986 raise AttributeAuthorityError("External Attribute Certificate "987 "must have an original "988 "provenance in order "989 "to make further mappings.")990 991 992 # Check it's valid and signed993 try:994 # Give path to CA cert to allow check995 userAttCert.certFilePathList = self.caCertFilePathList996 userAttCert.isValid(raiseExcep=True)997 998 except Exception, e:999 raise AttributeAuthorityError("Invalid Remote Attribute "1000 "Certificate: " + str(e))1001 1002 1003 # Check that's it's holder matches the candidate holder1004 # certificate DN1005 if holderX509Cert and userAttCert.holderDN != holderX509Cert.dn:1006 raise AttributeAuthorityError("User certificate and Attribute "1007 'Certificate DNs don\'t match: "%s"'1008 ' and "%s"' % (holderX509Cert.dn,1009 userAttCert.holderDN))1010 1011 1012 # Get roles from external Attribute Certificate1013 trustedHostRoles = userAttCert.roles1014 1015 1016 # Map external roles to local ones1017 localRoles = self.mapRemoteRoles2LocalRoles(1018 userAttCert['issuerName'],1019 trustedHostRoles)1020 if not localRoles:1021 raise AttributeAuthorityAccessDenied("No local roles mapped "1022 "to the %s roles: %s" %1023 (userAttCert['issuerName'],1024 ', '.join(trustedHostRoles)))1025 1026 attCert.addRoles(localRoles)1027 1028 1029 # Mark new Attribute Certificate as mapped1030 attCert.provenance = AttCert.mappedProvenance1031 1032 # Copy the user Id from the external AC1033 attCert.userId = userAttCert.userId1034 1035 # End set mapped certificate block1036 1037 try:1038 # Digitally sign certificate using Attribute Authority's1039 # certificate and private key1040 attCert.applyEnvelopedSignature()1041 1042 # Check the certificate is valid1043 attCert.isValid(raiseExcep=True)1044 1045 # Write out certificate to keep a record of it for auditing1046 #attCert.write()1047 self.__attCertLog.info(attCert)1048 1049 log.info('Issued an Attribute Certificate to "%s" with roles: '1050 '"%s"' % (userId, '", "'.join(attCert.roles)))1051 1052 # Return the cert to caller1053 return attCert1054 1055 except Exception, e:1056 raise AttributeAuthorityError('New Attribute Certificate "%s": %s'%1057 (attCert.filePath, e))1058 607 1059 608 def samlAttributeQuery(self, attributeQuery): … … 1175 724 1176 725 return samlResponse 1177 1178 def readMapConfig(self):1179 """Parse Map Configuration file.1180 """1181 log.debug("Reading map configuration file ...")1182 1183 try:1184 tree = ElementTree.parse(self.mapConfigFilePath)1185 rootElem = tree.getroot()1186 1187 except IOError, e:1188 raise AttributeAuthorityConfigError('Error parsing Map '1189 'Configuration file "%s": %s' %1190 (e.filename, e.strerror))1191 except Exception, e:1192 raise AttributeAuthorityConfigError('Error parsing Map '1193 'Configuration file: "%s": %s'%1194 (self.mapConfigFilePath, e))1195 1196 trustedElem = rootElem.findall('trusted')1197 if not trustedElem:1198 # Make an empty list so that for loop block below is skipped1199 # without an error1200 trustedElem = ()1201 1202 # Dictionaries:1203 # 1) to hold all the data1204 self.__mapConfig = {'thisHost': {}, 'trustedHosts': {}}1205 1206 # ... look-up1207 # 2) hosts corresponding to a given role and1208 # 3) roles of external data centre to this data centre1209 self.__localRole2TrustedHost = {}1210 self.__localRole2RemoteRole = {}1211 self.__remoteRole2LocalRole = {}1212 1213 # Information about this host1214 try:1215 thisHostElem = rootElem.findall('thisHost')[0]1216 1217 except Exception, e:1218 raise AttributeAuthorityConfigError('"thisHost" tag not found in '1219 'Map Configuration file "%s"' %1220 self.mapConfigFilePath)1221 1222 try:1223 hostName = thisHostElem.attrib.values()[0]1224 1225 except Exception, e:1226 raise AttributeAuthorityConfigError('"name" attribute of '1227 '"thisHost" element not found '1228 'in Map Configuration file '1229 '"%s"' %1230 self.mapConfigFilePath)1231 1232 # hostname is also stored in the AA's config file in the 'name' tag.1233 # Check the two match as the latter is copied into Attribute1234 # Certificates issued by this AA1235 #1236 # TODO: would be better to rationalise this so that the hostname is1237 # stored in one place only.1238 #1239 # P J Kershaw 14/06/061240 if hostName != self.name:1241 raise AttributeAuthorityError('"name" attribute of "thisHost" '1242 'element in Map Configuration file '1243 'doesn\'t match "name" element in '1244 'properties file.')1245 1246 # Information for THIS Attribute Authority1247 self.__mapConfig['thisHost'][hostName] = {}1248 1249 for k, v in AttributeAuthority.mapConfigHostDefaults.items():1250 val = thisHostElem.findtext(k)1251 if val is None and v == NotImplemented:1252 raise AttributeAuthorityConfigError('<thisHost> option <%s> '1253 'must be set.' % k)1254 self.__mapConfig['thisHost'][hostName][k] = val1255 1256 # Information about trusted hosts1257 for elem in trustedElem:1258 try:1259 trustedHost = elem.attrib.values()[0]1260 1261 except Exception, e:1262 raise AttributeAuthorityConfigError('Error reading trusted '1263 'host name: %s' % e)1264 1265 # Add signatureFile and list of roles1266 #1267 # (Currently Optional) additional tag allows query of the URI1268 # where a user would normally login at the trusted host. Added1269 # this feature to allow users to be forwarded to their home site1270 # if they are accessing a secure resource and are not1271 # authenticated1272 #1273 # P J Kershaw 25/05/061274 self.__mapConfig['trustedHosts'][trustedHost] = {}1275 for k, v in AttributeAuthority.mapConfigHostDefaults.items():1276 val = thisHostElem.findtext(k)1277 if val is None and v == NotImplemented:1278 raise AttributeAuthorityConfigError('<trustedHost> option '1279 '<%s> must be set.'%k)1280 1281 self.__mapConfig['trustedHosts'][trustedHost][k] = \1282 elem.findtext(k)1283 1284 roleElem = elem.findall('role')1285 if roleElem:1286 # Role keyword value requires special parsing before1287 # assignment1288 self.__mapConfig['trustedHosts'][trustedHost]['role'] = \1289 [dict(i.items()) for i in roleElem]1290 else:1291 # It's possible for trust relationships to not contain any1292 # role mapping. e.g. a site's login service trusting other1293 # sites login requests1294 self.__mapConfig['trustedHosts'][trustedHost]['role'] = []1295 1296 self.__localRole2RemoteRole[trustedHost] = {}1297 self.__remoteRole2LocalRole[trustedHost] = {}1298 1299 for role in self.__mapConfig['trustedHosts'][trustedHost]['role']:1300 try:1301 localRole = role['local']1302 remoteRole = role['remote']1303 except KeyError, e:1304 raise AttributeAuthorityError('Reading map configuration '1305 ' file "%s": no element '1306 '"%s" for host "%s"' %1307 (self.mapConfigFilePath,1308 e,1309 trustedHost))1310 1311 # Role to host look-up1312 if localRole in self.__localRole2TrustedHost:1313 1314 if trustedHost not in \1315 self.__localRole2TrustedHost[localRole]:1316 self.__localRole2TrustedHost[localRole].\1317 append(trustedHost)1318 else:1319 self.__localRole2TrustedHost[localRole] = [trustedHost]1320 1321 1322 # Trusted Host to local role and trusted host to trusted role1323 # map look-ups1324 try:1325 self.__remoteRole2LocalRole[trustedHost][remoteRole].\1326 append(localRole)1327 except KeyError:1328 self.__remoteRole2LocalRole[trustedHost][remoteRole] = \1329 [localRole]1330 1331 try:1332 self.__localRole2RemoteRole[trustedHost][localRole].\1333 append(remoteRole)1334 except KeyError:1335 self.__localRole2RemoteRole[trustedHost][localRole] = \1336 [remoteRole]1337 1338 # Store trusted host info look-up for retrieval by getTrustedHostInfo1339 # method1340 #1341 # Nb. {}.fromkeys([...]).keys() is a fudge to get unique elements1342 # from a list i.e. convert the list elements to a dict eliminating1343 # duplicated elements and convert the keys back into a list.1344 self._trustedHostInfo = dict(1345 [1346 (1347 k,1348 {1349 'siteName': v['siteName'],1350 'aaURI': v['aaURI'],1351 'aaDN': v['aaDN'],1352 'loginURI': v['loginURI'],1353 'loginServerDN': v['loginServerDN'],1354 'loginRequestServerDN': v['loginRequestServerDN'],1355 'role': {}.fromkeys([role['remote']1356 for role in v['role']]1357 ).keys()1358 }1359 ) for k, v in self.__mapConfig['trustedHosts'].items()1360 ])1361 1362 log.info('Loaded map configuration file "%s"' % self.mapConfigFilePath)1363 1364 726 1365 727 def getRoles(self, userId): … … 1381 743 raise AttributeAuthorityError("Getting user roles: %s" % e) 1382 744 1383 1384 def _getHostInfo(self):1385 """Return the host that this Attribute Authority represents: its ID,1386 the user login URI and WSDL address. Call this method via the1387 'hostInfo' property1388 1389 @rtype: dict1390 @return: dictionary of host information derived from the map1391 configuration"""1392 1393 return self.__mapConfig['thisHost']1394 1395 hostInfo = property(fget=_getHostInfo,1396 doc="Return information about this host")1397 1398 1399 def getTrustedHostInfo(self, role=None):1400 """Return a dictionary of the hosts that have trust relationships1401 with this AA. The dictionary is indexed by the trusted host name1402 and contains AA service, login URIs and the roles that map to the1403 given input local role.1404 1405 @type role: string1406 @param role: if set, return trusted hosts that having a mapping set1407 for this role. If no role is input, return all the AA's trusted hosts1408 with all their possible roles1409 1410 @rtype: dict1411 @return: dictionary of the hosts that have trust relationships1412 with this AA. It returns an empty dictionary if role isn't1413 recognised"""1414 1415 log.debug('Calling getTrustedHostInfo with role = "%s" ...' % role)1416 1417 if not self.__mapConfig or not self.__localRole2RemoteRole:1418 # This Attribute Authority has no trusted hosts1419 raise AttributeAuthorityNoTrustedHosts("The %s Attribute "1420 "Authority has no trusted "1421 "hosts" %1422 self.name)1423 1424 1425 if role is None:1426 # No role input - return all trusted hosts with their service URIs1427 # and the remote roles they map to1428 return self._trustedHostInfo1429 1430 else:1431 # Get trusted hosts for given input local role1432 try:1433 trustedHosts = self.__localRole2TrustedHost[role]1434 except:1435 raise AttributeAuthorityNoMatchingRoleInTrustedHosts(1436 'None of the trusted hosts have a mapping to the '1437 'input role "%s"' % role)1438 1439 1440 # Get associated Web service URI and roles for the trusted hosts1441 # identified and return as a dictionary indexed by host name1442 trustedHostInfo = dict(1443 [(1444 host,1445 {1446 'siteName': self.__mapConfig['trustedHosts'][host]['siteName'],1447 'aaURI': self.__mapConfig['trustedHosts'][host]['aaURI'],1448 'aaDN': self.__mapConfig['trustedHosts'][host]['aaDN'],1449 'loginURI': self.__mapConfig['trustedHosts'][host]['loginURI'],1450 'loginServerDN':1451 self.__mapConfig['trustedHosts'][host]['loginServerDN'],1452 'loginRequestServerDN':1453 self.__mapConfig['trustedHosts'][host]['loginRequestServerDN'],1454 'role': self.__localRole2RemoteRole[host][role]1455 }1456 ) for host in trustedHosts])1457 1458 return trustedHostInfo1459 1460 1461 def mapRemoteRoles2LocalRoles(self, trustedHost, trustedHostRoles):1462 """Map roles of trusted hosts to roles for this data centre1463 1464 @type trustedHost: string1465 @param trustedHost: name of external trusted data centre1466 @type trustedHostRoles: list1467 @param trustedHostRoles: list of external roles to map1468 @return: list of mapped roles"""1469 1470 if not self.__remoteRole2LocalRole:1471 raise AttributeAuthorityError("Roles map is not set - ensure "1472 "readMapConfig() has been called.")1473 1474 1475 # Check the host name is a trusted one recorded in the map1476 # configuration1477 if not self.__remoteRole2LocalRole.has_key(trustedHost):1478 return []1479 1480 # Add local roles, skipping if no mapping is found1481 localRoles = []1482 for trustedRole in trustedHostRoles:1483 if trustedRole in self.__remoteRole2LocalRole[trustedHost]:1484 localRoles.extend(1485 self.__remoteRole2LocalRole[trustedHost][trustedRole])1486 1487 return localRoles1488 1489 745 def getAttCertFactory(self): 1490 """Factory method to create SAML Attribute Q eury wrapper function746 """Factory method to create SAML Attribute Query wrapper function 1491 747 @rtype: function 1492 748 @return getAttCert method function wrapper … … 1521 777 return samlAttributeQueryWrapper 1522 778 1523 1524 from logging.handlers import RotatingFileHandler 1525 1526 # Inherit directly from Logger 1527 _loggerClass = logging.getLoggerClass() 1528 class AttCertLog(_loggerClass, object): 1529 """Log each Attribute Certificate issued using a rotating file handler 1530 so that the number of files held can be managed""" 1531 1532 def __init__(self, attCertFilePath, backUpCnt=1024): 1533 """Set up a rotating file handler to log ACs issued. 1534 @type attCertFilePath: string 1535 @param attCertFilePath: set where to store ACs. Set from 1536 AttributeAuthority properties file. 1537 1538 @type backUpCnt: int 1539 @param backUpCnt: set the number of files to store before rotating 1540 and overwriting old files.""" 1541 1542 if not isinstance(backUpCnt, int): 1543 raise TypeError('Expecting int type for "backUpCnt" keyword') 1544 1545 # Inherit from Logger class 1546 super(AttCertLog, self).__init__(name='', level=logging.INFO) 1547 1548 # Set a format for messages so that only the content of the AC is 1549 # logged, nothing else. 1550 formatter = logging.Formatter(fmt="", datefmt="") 1551 1552 # maxBytes is set to one so that only one AC will be written before 1553 # rotation to the next file 1554 fileLog = RotatingFileHandler(attCertFilePath, 1555 maxBytes=1, 1556 backupCount=backUpCnt) 1557 fileLog.setFormatter(formatter) 1558 self.addHandler(fileLog) 1559 1560 779 1561 780 class AttributeInterfaceError(Exception): 1562 781 """Exception handling for NDG Attribute Authority User Roles interface … … 1677 896 self.attributeMap = {} 1678 897 for line in lines: 1679 fields = re.split(',\ W*', line.strip())898 fields = re.split(',\s*', line.strip()) 1680 899 self.attributeMap[fields[0]] = fields[1:] 1681 900 -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/__init__.py
r6276 r6673 373 373 propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults) 374 374 375 CSV_PAT = re.compile(',\ W*')375 CSV_PAT = re.compile(',\s*') 376 376 377 377 # TODO: refactor to: -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/__init__.py
r6440 r6673 1315 1315 @rtype: basestring 1316 1316 @return: WSGI response''' 1317 """ 1317 """ 1318 if not isinstance(oidResponse, server.OpenIDResponse): 1319 log.error("OpenID Response is %r type, expecting %r", 1320 type(oidResponse), server.OpenIDResponse) 1321 return self._render.errorPage(environ, start_response, 1322 "Error setting a response. Please " 1323 "report this fault to your site " 1324 "administrator.", 1325 code=500) 1326 1318 1327 try: 1319 1328 webresponse = self.oidserver.encodeResponse(oidResponse) -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/axinterface/csv.py
r6354 r6673 91 91 nAttributes = len(self.attributeNames) 92 92 for line in lines: 93 fields = re.split(',\ W*', line.strip())93 fields = re.split(',\s*', line.strip()) 94 94 95 95 # Dictionary keyed by user ID with each val itself a dict keyed -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/ssl.py
r6557 r6673 368 368 ApacheSSLAuthnMiddleware.AUTHN_SUCCEEDED_ENVIRON_KEYNAME 369 369 ] = True 370 log.debug("Client Certificate DN %s matches DN in " 371 "permitted DNs list %r", dn, 372 self.clientCertDNMatchList) 370 373 return True 374 else: 375 log.debug("No match found for Client Certificate DN %s in " 376 "permitted DNs list %r", dn, self.clientCertDNMatchList) 371 377 372 378 return False
Note: See TracChangeset
for help on using the changeset viewer.