2 # GeniAPI authentication
7 from geni.util.faults import *
8 from geni.util.excep import *
9 from geni.util.credential import Credential
10 from geni.util.trustedroot import TrustedRootList
11 from geni.util.hierarchy import Hierarchy
12 from geni.util.rights import RightList
13 from geni.util.genitable import *
14 from geni.util.config import *
15 from geni.util.misc import *
19 Credential based authentication
22 def __init__(self, peer_cert = None, config = None ):
23 self.peer_cert = peer_cert
24 self.hierarchy = Hierarchy()
25 self.trusted_cert_list = TrustedRootList().get_list()
27 self.config = Config()
30 def check(self, cred, operation):
32 Check the credential against the peer cert (callerGID included
33 in the credential matches the caller that is connected to the
34 HTTPS connection, check if the credential was signed by a
35 trusted cert and check if the credential is allowd to perform
36 the specified operation.
38 self.client_cred = Credential(string = cred)
39 self.client_gid = self.client_cred.get_gid_caller()
40 self.object_gid = self.client_cred.get_gid_object()
42 # make sure the client_gid is not blank
43 if not self.client_gid:
44 raise MissingCallerGID(self.client_cred.get_subject())
46 # make sure the client_gid matches client's certificate
47 peer_cert = self.peer_cert
48 if not peer_cert.is_pubkey(self.client_gid.get_pubkey()):
49 raise ConnectionKeyGIDMismatch(self.client_gid.get_subject())
51 # make sure the client is allowed to perform the operation
53 if not self.client_cred.can_perform(operation):
54 raise InsufficientRights(operation)
56 if self.trusted_cert_list:
57 self.client_cred.verify_chain(self.trusted_cert_list)
59 self.client_gid.verify_chain(self.trusted_cert_list)
61 self.object_gid.verify_chain(self.trusted_cert_list)
66 def get_auth_info(self, auth_hrn):
68 Given an authority name, return the information for that authority.
69 This is basically a stub that calls the hierarchy module.
71 @param auth_hrn human readable name of authority
74 return self.hierarchy.get_auth_info(auth_hrn)
77 def get_auth_table(self, auth_name):
79 Given an authority name, return the database table for that authority.
80 If the databse table does not exist, then one will be automatically
83 @param auth_name human readable name of authority
85 auth_info = self.get_auth_info(auth_name)
86 table = GeniTable(hrn=auth_name,
87 cninfo=auth_info.get_dbinfo())
88 # if the table doesn't exist, then it means we haven't put any records
89 # into this authority yet.
91 if not table.exists():
92 print >> log, "Registry: creating table for authority", auth_name
97 def veriry_auth_belongs_to_me(self, name):
99 Verify that an authority belongs to our hierarchy.
100 This is basically left up to the implementation of the hierarchy
101 module. If the specified name does not belong, ane exception is
102 thrown indicating the caller should contact someone else.
104 @param auth_name human readable name of authority
107 self.get_auth_info(name)
110 def verify_object_belongs_to_me(self, name):
112 Verify that an object belongs to our hierarchy. By extension,
113 this implies that the authority that owns the object belongs
114 to our hierarchy. If it does not an exception is thrown.
116 @param name human readable name of object
118 auth_name = self.get_authority(name)
120 # the root authority belongs to the registry by default?
121 # TODO: is this true?
123 self.verify_auth_belongs_to_me(auth_name)
125 def verify_auth_belongs_to_me(self, name):
126 # get auth info will throw an exception if the authority doesnt exist
127 self.get_auth_info(name)
130 def verify_object_permission(self, name):
132 Verify that the object gid that was specified in the credential
133 allows permission to the object 'name'. This is done by a simple
134 prefix test. For example, an object_gid for plc.arizona would
135 match the objects plc.arizona.slice1 and plc.arizona.
137 @param name human readable name to test
139 object_hrn = self.object_gid.get_hrn()
140 if object_hrn == name:
142 if name.startswith(object_hrn + "."):
144 if name.startswith(get_authority(name)):
147 raise PermissionError(name)
149 def determine_user_rights(self, src_cred, record):
151 Given a user credential and a record, determine what set of rights the
152 user should have to that record.
154 Src_cred can be None when obtaining a user credential, but should be
155 set to a valid user credential when obtaining a slice or authority
158 This is intended to replace determine_rights() and
159 verify_cancreate_credential()
162 type = record.get_type()
164 cred_object_hrn = src_cred.get_gid_object().get_hrn()
166 # supplying src_cred==None is only valid when obtaining user
168 #assert(type == "user")
170 cred_object_hrn = None
175 researchers = record.get("researcher", [])
176 if (cred_object_hrn in researchers):
183 elif type == "authority":
184 pis = record.get("pi", [])
185 operators = record.get("operator", [])
186 rl.add("authority,sa,ma")
187 if (cred_object_hrn in pis):
189 if (cred_object_hrn in operators):
199 def verify_cancreate_credential(self, src_cred, record):
201 Verify that a user can retrive a particular type of credential.
202 For slices, the user must be on the researcher list. For SA and
203 MA the user must be on the pi and operator lists respectively
206 type = record.get_type()
207 cred_object_hrn = src_cred.get_gid_object().get_hrn()
208 if cred_object_hrn in [self.config.GENI_REGISTRY_ROOT_AUTH]:
211 researchers = record.get("researcher", [])
212 if not (cred_object_hrn in researchers):
213 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
215 pis = record.get("pi", [])
216 if not (cred_object_hrn in pis):
217 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
219 operators = record.get("operator", [])
220 if not (cred_object_hrn in operators):
221 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
223 def get_leaf(self, hrn):
224 parts = hrn.split(".")
225 return ".".join(parts[-1:])
227 def get_authority(self, hrn):
228 parts = hrn.split(".")
229 return ".".join(parts[:-1])
231 def hrn_to_pl_slicename(self, hrn):
232 parts = hrn.split(".")
233 return parts[-2] + "_" + parts[-1]
235 # assuming hrn is the hrn of an authority, return the plc authority name
236 def hrn_to_pl_authname(self, hrn):
237 parts = hrn.split(".")
240 # assuming hrn is the hrn of an authority, return the plc login_base
241 def hrn_to_pl_login_base(self, hrn):
242 return self.hrn_to_pl_authname(hrn)