Merge branch 'geni-v3' of ssh://git.onelab.eu/git/sfa into geni-v3
[sfa.git] / sfa / trust / credential_factory.py
1 #----------------------------------------------------------------------\r
2 # Copyright (c) 2014 Raytheon BBN Technologies\r
3 #\r
4 # Permission is hereby granted, free of charge, to any person obtaining\r
5 # a copy of this software and/or hardware specification (the "Work") to\r
6 # deal in the Work without restriction, including without limitation the\r
7 # rights to use, copy, modify, merge, publish, distribute, sublicense,\r
8 # and/or sell copies of the Work, and to permit persons to whom the Work\r
9 # is furnished to do so, subject to the following conditions:\r
10 #\r
11 # The above copyright notice and this permission notice shall be\r
12 # included in all copies or substantial portions of the Work.\r
13 #\r
14 # THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
16 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
17 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\r
18 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\r
19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
20 # OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS\r
21 # IN THE WORK.\r
22 #----------------------------------------------------------------------\r
23 \r
24 from sfa.util.sfalogging import logger\r
25 from sfa.trust.credential import Credential\r
26 from sfa.trust.abac_credential import ABACCredential\r
27 \r
28 import json\r
29 import re\r
30 \r
31 # Factory for creating credentials of different sorts by type.\r
32 # Specifically, this factory can create standard SFA credentials\r
33 # and ABAC credentials from XML strings based on their identifying content\r
34 \r
35 class CredentialFactory:\r
36 \r
37     UNKNOWN_CREDENTIAL_TYPE = 'geni_unknown'\r
38 \r
39     # Static Credential class method to determine the type of a credential\r
40     # string depending on its contents\r
41     @staticmethod\r
42     def getType(credString):\r
43         credString_nowhitespace = re.sub('\s', '', credString)\r
44         if credString_nowhitespace.find('<type>abac</type>') > -1:\r
45             return ABACCredential.ABAC_CREDENTIAL_TYPE\r
46         elif credString_nowhitespace.find('<type>privilege</type>') > -1:\r
47             return Credential.SFA_CREDENTIAL_TYPE\r
48         else:\r
49             st = credString_nowhitespace.find('<type>')\r
50             end = credString_nowhitespace.find('</type>', st)\r
51             return credString_nowhitespace[st + len('<type>'):end]\r
52 #            return CredentialFactory.UNKNOWN_CREDENTIAL_TYPE\r
53 \r
54     # Static Credential class method to create the appropriate credential\r
55     # (SFA or ABAC) depending on its type\r
56     @staticmethod\r
57     def createCred(credString=None, credFile=None):\r
58         if not credString and not credFile:\r
59             raise Exception("CredentialFactory.createCred called with no argument")\r
60         if credFile:\r
61             try:\r
62                 credString = open(credFile).read()\r
63             except Exception, e:\r
64                 logger.info("Error opening credential file %s: %s" % credFile, e)\r
65                 return None\r
66 \r
67         # Try to treat the file as JSON, getting the cred_type from the struct\r
68         try:\r
69             credO = json.loads(credString, encoding='ascii')\r
70             if credO.has_key('geni_value') and credO.has_key('geni_type'):\r
71                 cred_type = credO['geni_type']\r
72                 credString = credO['geni_value']\r
73         except Exception, e:\r
74             # It wasn't a struct. So the credString is XML. Pull the type directly from the string\r
75             logger.debug("Credential string not JSON: %s" % e)\r
76             cred_type = CredentialFactory.getType(credString)\r
77 \r
78         if cred_type == Credential.SFA_CREDENTIAL_TYPE:\r
79             try:\r
80                 cred = Credential(string=credString)\r
81                 return cred\r
82             except Exception, e:\r
83                 if credFile:\r
84                     msg = "credString started: %s" % credString[:50]\r
85                     raise Exception("%s not a parsable SFA credential: %s. " % (credFile, e) + msg)\r
86                 else:\r
87                     raise Exception("SFA Credential not parsable: %s. Cred start: %s..." % (e, credString[:50]))\r
88 \r
89         elif cred_type == ABACCredential.ABAC_CREDENTIAL_TYPE:\r
90             try:\r
91                 cred = ABACCredential(string=credString)\r
92                 return cred\r
93             except Exception, e:\r
94                 if credFile:\r
95                     raise Exception("%s not a parsable ABAC credential: %s" % (credFile, e))\r
96                 else:\r
97                     raise Exception("ABAC Credential not parsable: %s. Cred start: %s..." % (e, credString[:50]))\r
98         else:\r
99             raise Exception("Unknown credential type '%s'" % cred_type)\r
100 \r
101 if __name__ == "__main__":\r
102     c2 = open('/tmp/sfa.xml').read()\r
103     cred1 = CredentialFactory.createCred(credFile='/tmp/cred.xml')\r
104     cred2 = CredentialFactory.createCred(credString=c2)\r
105 \r
106     print "C1 = %s" % cred1\r
107     print "C2 = %s" % cred2\r
108     c1s = cred1.dump_string()\r
109     print "C1 = %s" % c1s\r
110 #    print "C2 = %s" % cred2.dump_string()\r