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 *
18 Credential based authentication
21 def __init__(self, peer_cert = None, config = None ):
22 self.peer_cert = peer_cert
23 self.hierarchy = Hierarchy()
24 self.trusted_cert_list = TrustedRootList().get_list()
26 self.config = Config()
29 def check(self, cred, operation):
31 Check the credential against the peer cert (callerGID included
32 in the credential matches the caller that is connected to the
33 HTTPS connection, check if the credential was signed by a
34 trusted cert and check if the credential is allowd to perform
35 the specified operation.
37 self.client_cred = Credential(string = cred)
38 self.client_gid = self.client_cred.get_gid_caller()
39 self.object_gid = self.client_cred.get_gid_object()
41 # make sure the client_gid is not blank
42 if not self.client_gid:
43 raise MissingCallerGID(self.client_cred.get_subject())
45 # make sure the client_gid matches client's certificate
46 peer_cert = self.peer_cert
47 if not peer_cert.is_pubkey(self.client_gid.get_pubkey()):
48 raise ConnectionKeyGIDMismatch(self.client_gid.get_subject())
50 # make sure the client is allowed to perform the operation
52 if not self.client_cred.can_perform(operation):
53 raise InsufficientRights(operation)
55 if self.trusted_cert_list:
56 self.client_cred.verify_chain(self.trusted_cert_list)
58 self.client_gid.verify_chain(self.trusted_cert_list)
60 self.object_gid.verify_chain(self.trusted_cert_list)
65 def get_auth_info(self, auth_hrn):
67 Given an authority name, return the information for that authority.
68 This is basically a stub that calls the hierarchy module.
70 @param auth_hrn human readable name of authority
73 return self.hierarchy.get_auth_info(auth_hrn)
76 def get_auth_table(self, auth_name):
78 Given an authority name, return the database table for that authority.
79 If the databse table does not exist, then one will be automatically
82 @param auth_name human readable name of authority
84 auth_info = self.get_auth_info(auth_name)
85 table = GeniTable(hrn=auth_name,
86 cninfo=auth_info.get_dbinfo())
87 # if the table doesn't exist, then it means we haven't put any records
88 # into this authority yet.
90 if not table.exists():
91 print >> log, "Registry: creating table for authority", auth_name
96 def veriry_auth_belongs_to_me(self, name):
98 Verify that an authority belongs to our hierarchy.
99 This is basically left up to the implementation of the hierarchy
100 module. If the specified name does not belong, ane exception is
101 thrown indicating the caller should contact someone else.
103 @param auth_name human readable name of authority
106 self.get_auth_info(name)
109 def verify_object_belongs_to_me(self, name):
111 Verify that an object belongs to our hierarchy. By extension,
112 this implies that the authority that owns the object belongs
113 to our hierarchy. If it does not an exception is thrown.
115 @param name human readable name of object
117 auth_name = self.get_authority(name)
119 # the root authority belongs to the registry by default?
120 # TODO: is this true?
122 self.verify_auth_belongs_to_me(auth_name)
124 def verify_auth_belongs_to_me(self, name):
125 # get auth info will throw an exception if the authority doesnt exist
126 self.get_auth_info(name)
129 def verify_object_permission(self, name):
131 Verify that the object gid that was specified in the credential
132 allows permission to the object 'name'. This is done by a simple
133 prefix test. For example, an object_gid for plc.arizona would
134 match the objects plc.arizona.slice1 and plc.arizona.
136 @param name human readable name to test
138 object_hrn = self.object_gid.get_hrn()
139 if object_hrn == name:
141 if name.startswith(object_hrn + "."):
143 raise PermissionError(name)
145 def determine_user_rights(self, src_cred, record):
147 Given a user credential and a record, determine what set of rights the
148 user should have to that record.
150 Src_cred can be None when obtaining a user credential, but should be
151 set to a valid user credential when obtaining a slice or authority
154 This is intended to replace determine_rights() and
155 verify_cancreate_credential()
158 type = record.get_type()
160 cred_object_hrn = src_cred.get_gid_object().get_hrn()
162 # supplying src_cred==None is only valid when obtaining user
164 assert(type == "user")
165 cred_object_hrn = None
170 researchers = record.get_geni_info().get("researcher", [])
171 if (cred_object_hrn in researchers):
178 elif type == "authority":
179 pis = record.get_geni_info().get("pi", [])
180 operators = record.get_geni_info().get("operator", [])
181 if (cred_object_hrn in pis):
183 if (cred_object_hrn in operators):
185 if (cred_object_hrn in pis) or (cred_object_hrn in operators):
195 def verify_cancreate_credential(self, src_cred, record):
197 Verify that a user can retrive a particular type of credential.
198 For slices, the user must be on the researcher list. For SA and
199 MA the user must be on the pi and operator lists respectively
202 type = record.get_type()
203 cred_object_hrn = src_cred.get_gid_object().get_hrn()
204 if cred_object_hrn in [self.config.GENI_REGISTRY_ROOT_AUTH]:
207 researchers = record.get_geni_info().get("researcher", [])
208 if not (cred_object_hrn in researchers):
209 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
211 pis = record.get_geni_info().get("pi", [])
212 if not (cred_object_hrn in pis):
213 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
215 operators = record.get_geni_info().get("operator", [])
216 if not (cred_object_hrn in operators):
217 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
219 def get_leaf(self, hrn):
220 parts = hrn.split(".")
221 return ".".join(parts[-1:])
223 def get_authority(self, hrn):
224 parts = hrn.split(".")
225 return ".".join(parts[:-1])
227 def hrn_to_pl_slicename(self, hrn):
228 parts = hrn.split(".")
229 return parts[-2] + "_" + parts[-1]
231 # assuming hrn is the hrn of an authority, return the plc authority name
232 def hrn_to_pl_authname(self, hrn):
233 parts = hrn.split(".")
236 # assuming hrn is the hrn of an authority, return the plc login_base
237 def hrn_to_pl_login_base(self, hrn):
238 return self.hrn_to_pl_authname(hrn)