reorganizing code. moving some things out of the server interface classes and into...
[sfa.git] / geni / util / auth.py
1 #
2 # GeniAPI authentication 
3 #
4 #
5
6 import time
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
15
16 class Auth:
17     """
18     Credential based authentication
19     """
20
21     def __init__(self, peer_cert):
22         self.peer_cert = peer_cert
23         self.hierarchy = Hierarchy()
24         self.trusted_cert_list = TrustedRootList().get_list() 
25
26     
27
28     def check(self, cred, operation):
29         """
30         Check the credential against the peer cert (callerGID included 
31         in the credential matches the caller that is connected to the 
32         HTTPS connection, check if the credential was signed by a 
33         trusted cert and check if the credential is allowd to perform 
34         the specified operation.    
35         """
36         self.client_cred = Credential(string = cred)
37         self.client_gid = self.client_cred.get_gid_caller()
38         self.object_gid = self.client_cred.get_gid_object()
39         
40         # make sure the client_gid is not blank
41         if not self.client_gid:
42             raise MissingCallerGID(self.client_cred.get_subject())
43
44         # make sure the client_gid matches client's certificate
45         peer_cert = self.peer_cert
46         if not peer_cert.is_pubkey(self.client_gid.get_pubkey()):
47             raise ConnectionKeyGIDMismatch(self.client_gid.get_subject())
48
49         # make sure the client is allowed to perform the operation
50         if operation:
51             if not self.client_cred.can_perform(operation):
52                 raise InsufficientRights(operation)
53
54         if self.trusted_cert_list:
55             self.client_cred.verify_chain(self.trusted_cert_list)
56             if self.client_gid:
57                 self.client_gid.verify_chain(self.trusted_cert_list)
58             if self.object_gid:
59                 self.object_gid.verify_chain(self.trusted_cert_list)
60
61         return True
62
63         
64     def get_auth_info(self, auth_hrn):
65         """
66         Given an authority name, return the information for that authority.
67         This is basically a stub that calls the hierarchy module.
68         
69         @param auth_hrn human readable name of authority  
70         """
71
72         return self.hierarchy.get_auth_info(auth_hrn)
73
74
75     def get_auth_table(self, auth_name):
76         """
77         Given an authority name, return the database table for that authority.
78         If the databse table does not exist, then one will be automatically
79         created.
80
81         @param auth_name human readable name of authority
82         """
83         auth_info = self.get_auth_info(auth_name)
84         table = GeniTable(hrn=auth_name,
85                           cninfo=auth_info.get_dbinfo())
86         # if the table doesn't exist, then it means we haven't put any records
87         # into this authority yet.
88
89         if not table.exists():
90             print >> log, "Registry: creating table for authority", auth_name
91             table.create()
92     
93         return table
94
95     def veriry_auth_belongs_to_me(self, name):
96         """
97         Verify that an authority belongs to our hierarchy. 
98         This is basically left up to the implementation of the hierarchy
99         module. If the specified name does not belong, ane exception is 
100         thrown indicating the caller should contact someone else.
101
102         @param auth_name human readable name of authority
103         """
104
105         self.get_auth_info(name)
106
107
108     def verify_object_belongs_to_me(self, name):
109         """
110         Verify that an object belongs to our hierarchy. By extension,
111         this implies that the authority that owns the object belongs
112         to our hierarchy. If it does not an exception is thrown.
113     
114         @param name human readable name of object        
115         """
116         auth_name = self.get_authority(name)
117         if not auth_name:
118             # the root authority belongs to the registry by default?
119             # TODO: is this true?
120             return
121         self.verify_auth_belongs_to_me(auth_name) 
122              
123     def verify_auth_belongs_to_me(self, name):
124         # get auth info will throw an exception if the authority doesnt exist
125         self.get_auth_info(name) 
126
127
128     def verify_object_permission(self, name):
129         """
130         Verify that the object gid that was specified in the credential
131         allows permission to the object 'name'. This is done by a simple
132         prefix test. For example, an object_gid for plc.arizona would 
133         match the objects plc.arizona.slice1 and plc.arizona.
134     
135         @param name human readable name to test  
136         """
137         object_hrn = self.object_gid.get_hrn()
138         if object_hrn == name:
139             return
140         if name.startswith(object_hrn + "."):
141             return
142         raise PermissionError(name)
143   
144     def verify_cancreate_credential(self, src_cred, record):
145         """
146         Verify that a user can retrive a particular type of credential. 
147         For slices, the user must be on the researcher list. For SA and
148         MA the user must be on the pi and operator lists respectively 
149         """
150
151         type = record.get_type()
152         cred_object_hrn = src_cred.get_gid_object().get_hrn()
153         if cred_object_hrn in [self.config.GENI_REGISTRY_ROOT_AUTH]:
154             return
155         if type=="slice":
156             researchers = record.get_geni_info().get("researcher", [])
157             if not (cred_object_hrn in researchers):
158                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
159         elif type == "sa":
160             pis = record.get_geni_info().get("pi", [])
161             if not (cred_object_hrn in pis):
162                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
163         elif type == "ma":
164             operators = record.get_geni_info().get("operator", [])
165             if not (cred_object_hrn in operators):
166                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
167
168     def get_leaf(self, hrn):
169         parts = hrn.split(".")
170         return ".".join(parts[-1:])
171
172     def get_authority(self, hrn):
173
174         parts = hrn.split(".")
175         return ".".join(parts[:-1])
176
177     def get_auth_type(self, type):
178         if (type=="slice") or (type=="user") or (type=="sa"):
179             return "sa"
180         elif (type=="component") or (type=="ma"):
181             return "ma"
182         else:
183             raise UnknownGeniType(type)
184
185     def hrn_to_pl_slicename(self, hrn):
186         parts = hrn.split(".")
187         return parts[-2] + "_" + parts[-1]
188
189     # assuming hrn is the hrn of an authority, return the plc authority name
190     def hrn_to_pl_authname(self, hrn):
191         parts = hrn.split(".")
192         return parts[-1]
193
194     # assuming hrn is the hrn of an authority, return the plc login_base
195     def hrn_to_pl_login_base(self, hrn):
196         return self.hrn_to_pl_authname(hrn)
197