Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

#!/usr/bin/env python  

""" 

@file ion/integration/ais/RegisterUser/RegisterUser.py 

@author Bill Bollenbcher 

@brief The worker class that implements the RegisterUser function for the AIS  (workflow #107) 

""" 

 

import ion.util.ionlog 

log = ion.util.ionlog.getLogger(__name__) 

import logging 

from twisted.internet import defer 

 

from ion.services.coi.identity_registry import IdentityRegistryClient 

from ion.core.exception import ReceivedApplicationError 

from ion.core.intercept.policy import subject_has_admin_role, \ 

                                      subject_has_early_adopter_role, \ 

                                      subject_has_marine_operator_role, \ 

                                      subject_has_data_provider_role, \ 

                                      user_has_admin_role, \ 

                                      user_has_early_adopter_role, \ 

                                      user_has_marine_operator_role, \ 

                                      user_has_data_provider_role, \ 

                                      map_ooi_id_to_subject_admin_role, \ 

                                      map_ooi_id_to_subject_early_adopter_role, \ 

                                      map_ooi_id_to_subject_marine_operator_role, \ 

                                      map_ooi_id_to_subject_data_provider_role 

 

from ion.integration.ais.ais_object_identifiers import AIS_RESPONSE_MSG_TYPE, \ 

                                                       AIS_REQUEST_MSG_TYPE, \ 

                                                       AIS_RESPONSE_ERROR_TYPE, \ 

                                                       REGISTER_USER_RESPONSE_TYPE, \ 

                                                       GET_USER_PROFILE_RESPONSE_TYPE 

from ion.core.object import object_utils 

from ion.core.security.authentication import Authentication 

 

IDENTITY_TYPE = object_utils.create_type_identifier(object_id=1401, version=1) 

""" 

from ion-object-definitions/net/ooici/services/coi/identity/identity_management.proto 

message UserIdentity { 

   enum _MessageTypeIdentifier { 

       _ID = 1401; 

       _VERSION = 1; 

   } 

 

   // objects in a protofile are called messages 

 

   optional string subject=1; 

   optional string certificate=2; 

   optional string rsa_private_key=3; 

   optional string dispatcher_queue=4 

   optional string email=5 

   optional string life_cycle_state=6; 

} 

""""" 

 

USER_OOIID_TYPE = object_utils.create_type_identifier(object_id=1403, version=1) 

""" 

from ion-object-definitions/net/ooici/services/coi/identity/identity_management.proto 

message UserOoiId { 

   enum _MessageTypeIdentifier { 

       _ID = 1403; 

       _VERSION = 1; 

   } 

 

   // objects in a protofile are called messages 

 

   optional string ooi_id=1; 

} 

""" 

 

RESOURCE_CFG_REQUEST_TYPE = object_utils.create_type_identifier(object_id=10, version=1) 

""" 

from ion-object-definitions/net/ooici/core/message/resource_request.proto 

message ResourceConfigurationRequest{ 

    enum _MessageTypeIdentifier { 

      _ID = 10; 

      _VERSION = 1; 

    } 

     

    // The identifier for the resource to configure 

    optional net.ooici.core.link.CASRef resource_reference = 1; 

 

    // The desired configuration object 

    optional net.ooici.core.link.CASRef configuration = 2; 

""" 

 

RESOURCE_CFG_RESPONSE_TYPE = object_utils.create_type_identifier(object_id=12, version=1) 

""" 

from ion-object-definitions/net/ooici/core/message/resource_request.proto 

message ResourceConfigurationResponse{ 

    enum _MessageTypeIdentifier { 

      _ID = 12; 

      _VERSION = 1; 

    } 

     

    // The identifier for the resource to configure 

    optional net.ooici.core.link.CASRef resource_reference = 1; 

 

    // The desired configuration object 

    optional net.ooici.core.link.CASRef configuration = 2; 

     

    optional string result = 3; 

} 

""" 

 

class RegisterUser(object): 

 

   def __init__(self, ais): 

      log.debug('RegisterUser.__init__()') 

      self.irc = IdentityRegistryClient(proc=ais) 

      self.mc = ais.mc 

 

 

   @defer.inlineCallbacks 

   def getUser (self, msg): 

      if log.getEffectiveLevel() <= logging.DEBUG: 

         log.debug('RegisterUser.getUser()\n'+str(msg)) 

 

      # check that the GPB is correct type & has a payload 

      result = yield self._CheckRequest(msg) 

      if result != None: 

         result.error_str = "AIS.getUser: " + result.error_str 

         defer.returnValue(result) 

 

      # check that ooi_id is present in GPB 

      if not msg.message_parameters_reference.IsFieldSet('user_ooi_id'): 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

         Response.error_num = Response.ResponseCodes.BAD_REQUEST 

         Response.error_str = "AIS.getUser: Required field [user_ooi_id] not found in message" 

         defer.returnValue(Response) 

 

      # build the Identity Registry request for get_user message 

      Request = yield self.mc.create_instance(RESOURCE_CFG_REQUEST_TYPE, MessageName='IR request') 

      Request.configuration = Request.CreateObject(USER_OOIID_TYPE) 

      Request.configuration.ooi_id = msg.message_parameters_reference.user_ooi_id 

 

      # get the user information from the Identity Registry  

      try: 

         user_info = yield self.irc.get_user(Request) 

      except ReceivedApplicationError, ex: 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS getUser error response') 

         Response.error_num = ex.msg_content.MessageResponseCode 

         Response.error_str = 'AIS.getUser: Error calling IR.get_user: '+ex.msg_content.MessageResponseBody 

         defer.returnValue(Response) 

 

      # build AIS response 

      Response = yield self.mc.create_instance(AIS_RESPONSE_MSG_TYPE, MessageName='AIS getUser response') 

      Response.message_parameters_reference.add() 

      Response.message_parameters_reference[0] = Response.CreateObject(GET_USER_PROFILE_RESPONSE_TYPE) 

      if user_info.resource_reference.IsFieldSet('name'): 

         Response.message_parameters_reference[0].name = user_info.resource_reference.name 

      if user_info.resource_reference.IsFieldSet('institution'): 

         Response.message_parameters_reference[0].institution = user_info.resource_reference.institution 

      if user_info.resource_reference.IsFieldSet('email'): 

         Response.message_parameters_reference[0].email_address = user_info.resource_reference.email 

      if user_info.resource_reference.IsFieldSet('authenticating_organization'): 

         Response.message_parameters_reference[0].authenticating_organization = user_info.resource_reference.authenticating_organization 

      if user_info.resource_reference.IsFieldSet('profile'): 

         i = 0 

         for item in user_info.resource_reference.profile: 

            log.debug('getUser: setting profile to '+str(item)) 

            Response.message_parameters_reference[0].profile.add() 

            Response.message_parameters_reference[0].profile[i].name = item.name 

            Response.message_parameters_reference[0].profile[i].value = item.value 

            i = i + 1 

      Response.result = Response.ResponseCodes.OK 

      defer.returnValue(Response) 

 

 

   @defer.inlineCallbacks 

   def updateUserProfile (self, msg): 

      if log.getEffectiveLevel() <= logging.DEBUG: 

         log.debug('RegisterUser.updateUserProfile()\n'+str(msg)) 

 

      # check that the GPB is correct type & has a payload 

      result = yield self._CheckRequest(msg) 

      if result != None: 

         result.error_str = "AIS.updateUserProfile: " + result.error_str 

         defer.returnValue(result) 

 

      # check that ooi_id is present in GPB 

      if not msg.message_parameters_reference.IsFieldSet('user_ooi_id'): 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

         Response.error_num = Response.ResponseCodes.BAD_REQUEST 

         Response.error_str = "AIS.updateUserProfile: Required field [user_ooi_id] not found in message" 

         defer.returnValue(Response) 

 

      # build the Identity Registry request for get_user message 

      Request = yield self.mc.create_instance(RESOURCE_CFG_REQUEST_TYPE, MessageName='IR request') 

      Request.configuration = Request.CreateObject(USER_OOIID_TYPE) 

      Request.configuration.ooi_id = msg.message_parameters_reference.user_ooi_id 

 

      # get the user information from the Identity Registry  

      try: 

         user_info = yield self.irc.get_user(Request) 

      except ReceivedApplicationError, ex: 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS updateUserProfile error response') 

         Response.error_num = ex.msg_content.MessageResponseCode 

         Response.error_str = 'AIS.updateUserProfile: Error calling IR.get_user: '+ex.msg_content.MessageResponseBody 

         defer.returnValue(Response) 

 

      # build the Identity Registry request for update_user_profile message 

      Request.configuration = Request.CreateObject(IDENTITY_TYPE) 

      Request.configuration.subject = user_info.resource_reference.subject 

 

      # check to see if name is present in GPB 

      if msg.message_parameters_reference.IsFieldSet('name'): 

         Request.configuration.name = msg.message_parameters_reference.name 

 

      # check to see if institution is present in GPB 

      if msg.message_parameters_reference.IsFieldSet('institution'): 

         Request.configuration.institution = msg.message_parameters_reference.institution 

 

      # check to see if email address is present in GPB 

      if msg.message_parameters_reference.IsFieldSet('email_address'): 

         Request.configuration.email = msg.message_parameters_reference.email_address 

 

      # check to see if profile is present in GPB 

      if msg.message_parameters_reference.IsFieldSet('profile'): 

         i = 0 

         for item in msg.message_parameters_reference.profile: 

             log.debug('updateUserProfile: adding to profile - '+str(item)) 

             Request.configuration.profile.add() 

             Request.configuration.profile[i].name = item.name 

             Request.configuration.profile[i].value = item.value 

             i = i + 1 

 

      # update the profile for the user   

      try: 

         result = yield self.irc.update_user_profile(Request) 

      except ReceivedApplicationError, ex: 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS updateUserProfile error response') 

         Response.error_num = ex.msg_content.MessageResponseCode 

         Response.error_str = 'AIS.updateUserProfile: Error calling IR.update_user_profile: '+ex.msg_content.MessageResponseBody 

         defer.returnValue(Response) 

 

      # build AIS response 

      Response = yield self.mc.create_instance(AIS_RESPONSE_MSG_TYPE, MessageName='AIS updateUserProfile response') 

      Response.result = Response.ResponseCodes.OK 

      defer.returnValue(Response) 

 

 

   @defer.inlineCallbacks 

   def registerUser (self, msg): 

      if log.getEffectiveLevel() <= logging.DEBUG: 

         log.debug('RegisterUser.registerUser()\n'+str(msg)) 

 

      # check that the GPB is correct type & has a payload 

      result = yield self._CheckRequest(msg) 

      if result != None: 

         result.error_str = "AIS.registerUser: " + result.error_str 

         defer.returnValue(result) 

 

      # check that certificate is present in GPB 

      if not msg.message_parameters_reference.IsFieldSet('certificate'): 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

         Response.error_num = Response.ResponseCodes.BAD_REQUEST 

         Response.error_str = "AIS.registerUser: Required field [certificate] not found in message" 

         defer.returnValue(Response) 

 

      # check that key is present in GPB 

      if not msg.message_parameters_reference.IsFieldSet('rsa_private_key'): 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

         Response.error_num = Response.ResponseCodes.BAD_REQUEST 

         Response.error_str = "AIS.registerUser: Required field [key] not found in message" 

         defer.returnValue(Response) 

 

      # build Identity Registry request for authenticate_user message 

      Request = yield self.mc.create_instance(RESOURCE_CFG_REQUEST_TYPE, MessageName='IR request') 

      Request.configuration = Request.CreateObject(IDENTITY_TYPE) 

      Request.configuration.certificate = msg.message_parameters_reference.certificate 

      Request.configuration.rsa_private_key = msg.message_parameters_reference.rsa_private_key 

 

      # use authenticate_user to try to update a possibly already existing user  

      try: 

         result = yield self.irc.authenticate_user(Request) 

         log.debug('AIS.registerUser: user exists in IR with ooi_id = %s'%str(result.resource_reference.ooi_id)) 

         UserAlreadyRegistered = True 

      except ReceivedApplicationError, ex: 

            log.info("AIS.registerUser: calling irc.register_user with\n"+str(Request.configuration)) 

            # user wasn't in Identity Registry, so register them now 

            try: 

               result = yield self.irc.register_user(Request) 

               if log.getEffectiveLevel() <= logging.DEBUG: 

                  log.debug('AIS.registerUser: added new user in IR with ooi_id = '+str(result)) 

               UserAlreadyRegistered = False 

            except ReceivedApplicationError, ex: 

               log.info('AIS.registerUser: Error invoking Identity Registry Service: %s' %ex) 

               # build AIS error response 

               Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS RegisterUser error response') 

               Response.error_num = ex.msg_content.MessageResponseCode 

               Response.error_str = 'AIS.registerUser: Error calling IR.register_user: '+ex.msg_content.MessageResponseBody 

               defer.returnValue(Response) 

 

      # Get subject from certificate to allow lookup of user roles/attributes 

      authentication = Authentication() 

      cert_info = authentication.decode_certificate(str(Request.configuration.certificate)) 

      subject = cert_info['subject'] 

 

      # build AIS response with user's ooi_id 

      ooi_id = result.resource_reference.ooi_id 

      Response = yield self.mc.create_instance(AIS_RESPONSE_MSG_TYPE, MessageName='AIS RegisterUser response') 

      Response.message_parameters_reference.add() 

      Response.message_parameters_reference[0] = Response.CreateObject(REGISTER_USER_RESPONSE_TYPE) 

      Response.message_parameters_reference[0].ooi_id = ooi_id 

      Response.message_parameters_reference[0].user_already_registered = UserAlreadyRegistered 

 

      # Obtain extra user roles/attributes, first trying subject then ooid. In case of 

      # subject match, also call mapping methods to add ooi_id to role lookup 

      # for use by policy management interceptor 

      if subject_has_admin_role(subject): 

          Response.message_parameters_reference[0].user_is_admin = True 

          map_ooi_id_to_subject_admin_role(subject, ooi_id) 

      else: 

          if user_has_admin_role(ooi_id): 

              Response.message_parameters_reference[0].user_is_admin = True 

          else: 

              Response.message_parameters_reference[0].user_is_admin = False 

      if subject_has_early_adopter_role(subject): 

          Response.message_parameters_reference[0].user_is_early_adopter = True 

          map_ooi_id_to_subject_early_adopter_role(subject, ooi_id) 

      else: 

          if user_has_early_adopter_role(ooi_id): 

              Response.message_parameters_reference[0].user_is_early_adopter = True 

          else: 

              Response.message_parameters_reference[0].user_is_early_adopter = False 

      if subject_has_data_provider_role(subject): 

          Response.message_parameters_reference[0].user_is_data_provider = True 

          map_ooi_id_to_subject_data_provider_role(subject, ooi_id) 

      else: 

          if user_has_data_provider_role(ooi_id): 

              Response.message_parameters_reference[0].user_is_data_provider = True 

          else: 

              Response.message_parameters_reference[0].user_is_data_provider = False 

      if subject_has_marine_operator_role(subject): 

          Response.message_parameters_reference[0].user_is_marine_operator = True 

          map_ooi_id_to_subject_marine_operator_role(subject, ooi_id) 

      else: 

          if user_has_marine_operator_role(ooi_id): 

              Response.message_parameters_reference[0].user_is_marine_operator = True 

          else: 

              Response.message_parameters_reference[0].user_is_marine_operator = False 

      Response.result = Response.ResponseCodes.OK 

      defer.returnValue(Response) 

 

   @defer.inlineCallbacks 

   def setUserRole(self, msg): 

      # check that the GPB is correct type & has a payload 

      result = yield self._CheckRequest(msg) 

      if result != None: 

         result.error_str = "AIS.setUserRole: " + result.error_str 

         defer.returnValue(result) 

 

      # check that required fields are present in GPB 

      for fieldName in ('user_ooi_id', 'role'): 

         if not msg.message_parameters_reference.IsFieldSet(fieldName): 

            # build AIS error response 

            Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

            Response.error_num = Response.ResponseCodes.BAD_REQUEST 

            Response.error_str = "AIS.updateUserProfile: Required field [%s] not found in message" % (fieldName) 

            defer.returnValue(Response) 

 

      user_id, role = msg.message_parameters_reference.user_ooi_id, msg.message_parameters_reference.role 

      try: 

          yield self.irc.set_role(user_id, role) 

      except ReceivedApplicationError, ex: 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS setUserRole error response') 

         Response.error_num = ex.msg_content.MessageResponseCode 

         Response.error_str = 'AIS.setUserRole: Error calling IR.set_role: '+ex.msg_content.MessageResponseBody 

         defer.returnValue(Response) 

 

      # build AIS response 

      Response = yield self.mc.create_instance(AIS_RESPONSE_MSG_TYPE, MessageName='AIS setUserRole response') 

      Response.result = Response.ResponseCodes.OK 

      defer.returnValue(Response) 

 

 

   @defer.inlineCallbacks 

   def _CheckRequest(self, request): 

      # Check for correct request protocol buffer type 

      if request.MessageType != AIS_REQUEST_MSG_TYPE: 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

         Response.error_num = Response.ResponseCodes.BAD_REQUEST 

         Response.error_str = 'Bad message type receieved, ignoring' 

         defer.returnValue(Response) 

 

      # Check payload in message 

      if not request.IsFieldSet('message_parameters_reference'): 

         # build AIS error response 

         Response = yield self.mc.create_instance(AIS_RESPONSE_ERROR_TYPE, MessageName='AIS error response') 

         Response.error_num = Response.ResponseCodes.BAD_REQUEST 

         Response.error_str = "Required field [message_parameters_reference] not found in message" 

         defer.returnValue(Response) 

 

      defer.returnValue(None)