added request_hash argument. authenticate the credential using request_hash
[sfa.git] / sfa / methods / register.py
1 ### $Id$
2 ### $URL$
3
4 from sfa.trust.certificate import Keypair, convert_public_key
5 from sfa.trust.gid import *
6
7 from sfa.util.faults import *
8 from sfa.util.misc import *
9 from sfa.util.method import Method
10 from sfa.util.parameter import Parameter, Mixed
11 from sfa.util.record import GeniRecord
12 from sfa.util.genitable import GeniTable
13 from sfa.util.debug import log
14 from sfa.trust.auth import Auth
15 from sfa.trust.gid import create_uuid
16 from sfa.trust.credential import Credential
17
18 class register(Method):
19     """
20     Register an object with the registry. In addition to being stored in the
21     Geni database, the appropriate records will also be created in the
22     PLC databases
23     
24     @param cred credential string
25     @param record_dict dictionary containing record fields
26     
27     @return gid string representation
28     """
29
30     interfaces = ['registry']
31     
32     accepts = [
33         Parameter(str, "Credential string"),
34         Parameter(dict, "Record dictionary containing record fields"),
35         Parameter(str, "Request hash")
36         ]
37
38     returns = Parameter(int, "String representation of gid object")
39     
40     def call(self, cred, record_dict, request_hash, caller_cred=None):
41         self.api.auth.authenticateCred(cred, [cred, record_dict], request_hash)
42         self.api.auth.check(cred, "register")
43         if caller_cred==None:
44                 caller_cred=cred
45         
46         #log the call
47         self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, Credential(string=caller_cred).get_gid_caller().get_hrn(), None, self.name))
48         record = GeniRecord(dict = record_dict)
49         record['authority'] = get_authority(record['hrn'])
50         type = record['type']
51         hrn = record['hrn']
52         self.api.auth.verify_object_permission(hrn)
53         auth_info = self.api.auth.get_auth_info(record['authority'])
54         pub_key = None  
55         # make sure record has a gid
56         if 'gid' not in record:
57             uuid = create_uuid()
58             pkey = Keypair(create=True)
59             if 'key' in record and record['key']:
60                 if isinstance(record['key'], list):
61                     pub_key = record['key'][0]
62                 else:
63                     pub_key = record['key']
64                 pkey = convert_public_key(pub_key)
65             
66             gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
67             gid = gid_object.save_to_string(save_parents=True)
68             record['gid'] = gid
69             record.set_gid(gid)
70
71         # check if record already exists
72         table = GeniTable()
73         existing_records = table.find({'type': type, 'hrn': hrn})
74         if existing_records:
75             raise ExistingRecord(hrn)
76         else:
77             # We will update the pointer later
78             record['pointer'] = -1 
79             record.set_pointer(-1)
80             record_id = table.insert(record)
81             record['record_id'] = record_id
82  
83         if type in ["authority"]:
84             # update the tree
85             if not self.api.auth.hierarchy.auth_exists(hrn):
86                 self.api.auth.hierarchy.create_auth(hrn)
87
88             # authorities are special since they are managed by the registry
89             # rather than by the caller. We create our own GID for the
90             # authority rather than relying on the caller to supply one.
91
92             # get the GID from the newly created authority
93             gid = auth_info.get_gid_object()
94             record.set_gid(gid.save_to_string(save_parents=True))
95
96             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
97             sites = self.api.plshell.GetSites(self.api.plauth, [pl_record['login_base']])
98             if not sites:    
99                 pointer = self.api.plshell.AddSite(self.api.plauth, pl_record)
100             else:
101                 pointer = sites[0]['site_id']
102
103             record.set_pointer(pointer)
104
105         elif (type == "slice"):
106             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
107             slices = self.api.plshell.GetSlices(self.api.plauth, [pl_record['name']])
108             if not slices: 
109                 pointer = self.api.plshell.AddSlice(self.api.plauth, pl_record)
110             else:
111                 pointer = slices[0]['slice_id']
112             record.set_pointer(pointer)
113
114         elif  (type == "user"):
115             persons = self.api.plshell.GetPersons(self.api.plauth, [record['email']])
116             if not persons:
117                 pointer = self.api.plshell.AddPerson(self.api.plauth, dict(record))
118             else:
119                 pointer = persons[0]['person_id']
120  
121             if 'enabled' in record and record['enabled']:
122                 self.api.plshell.UpdatePerson(self.api.plauth, pointer, {'enabled': record['enabled']})
123             # add this persons to the site only if he is being added for the first
124             # time by sfa and doesont already exist in plc     
125             if not persons or not persons[0]['site_ids']:
126                 login_base = get_leaf(record['authority'])
127                 self.api.plshell.AddPersonToSite(self.api.plauth, pointer, login_base)
128         
129             # What roles should this user have?
130             self.api.plshell.AddRoleToPerson(self.api.plauth, 'user', pointer) 
131             record.set_pointer(pointer)
132             # Add the user's key
133             if pub_key:
134                 self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key})
135
136         elif (type == "node"):
137             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
138             login_base = hrn_to_pl_login_base(record['authority'])
139             nodes = self.api.plshell.GetNodes(self.api.plauth, [pl_record['hostname']])
140             if not nodes:
141                 pointer = self.api.plshell.AddNode(self.api.plauth, login_base, pl_record)
142             else:
143                 pointer = nodes[0]['node_id']
144             record.set_pointer(pointer)
145
146         else:
147             raise UnknownGeniType(type)
148
149         table.update(record)
150
151         # update membership for researchers, pis, owners, operators
152         self.api.update_membership(None, record)
153
154         return record.get_gid_object().save_to_string(save_parents=True)