def save_token(token, request, *args, **kwargs): """ Callback to persist newly created token. """ log.info("OAuth:save_token(%s)", token) current_time = get_ion_ts_millis() # Note: token["expires_in"] was initialized by the framework and is not correct expires = str(current_time + 1000 * ui_instance.session_timeout) # Str millis actor_id = flask.g.actor_id access_token_str = str(token["access_token"]) refresh_token_str = str(token["refresh_token"]) scopes = str(token["scope"]) # Access token token_obj = SecurityToken(token_type=TokenTypeEnum.OAUTH_ACCESS, token_string=access_token_str, expires=expires, status="OPEN", actor_id=actor_id, attributes=dict(access_token=access_token_str, refresh_token=refresh_token_str, scopes=scopes, client_id=request.client.client_id, ts_created=current_time)) token_id = "access_token_%s" % access_token_str ui_instance.container.object_store.create(token_obj, token_id) # Refresh token token_obj = SecurityToken(token_type=TokenTypeEnum.OAUTH_REFRESH, token_string=refresh_token_str, expires=expires, status="OPEN", actor_id=actor_id, attributes=dict(access_token=access_token_str, refresh_token=refresh_token_str, scopes=scopes, client_id=request.client.client_id, ts_created=current_time)) token_id = "refresh_token_%s" % refresh_token_str ui_instance.container.object_store.create(token_obj, token_id) if ui_instance.remember_user: # Store user_id and access_token within server session, so that a client can resume flask.session["access_token"] = access_token_str flask.session["actor_id"] = actor_id
def check_authentication_token(self, token_string=''): """Checks given token and returns a dict with actor id if valid. @param token_string str @retval token_info dict @throws BadRequest Illegal parameter type of value @throws NotFound Token string not found @throws Unauthorized Token not valid anymore or otherwise """ token_id = "token_%s" % token_string token = self.container.object_store.read(token_id) if not isinstance(token, SecurityToken): raise Inconsistent("Token illegal type") if token.token_type != TokenTypeEnum.ACTOR_AUTH: raise BadRequest("Illegal token type") if token.token_string != token_string: raise Inconsistent("Found token's token_string does not match") cur_time = get_ion_ts_millis() if token.status != "OPEN": raise Unauthorized("Token status invalid") if cur_time >= int(token.expires): raise Unauthorized("Token expired") token_info = dict(actor_id=token.actor_id, expiry=token.expires, token=token, token_id=token_id) log.info("Authentication token %s resolved to actor %s, expiry %s", token_string, token.actor_id, token.expires) return token_info
def check_authentication_token(self, token_string=''): """Checks given token and returns a dict with actor id if valid. """ token_id = "token_%s" % token_string token = self.container.object_store.read(token_id) if not isinstance(token, SecurityToken): raise Inconsistent("Token illegal type") if token.token_type != TokenTypeEnum.ACTOR_AUTH: raise BadRequest("Illegal token type") if token.token_string != token_string: raise Inconsistent("Found token's token_string does not match") cur_time = get_ion_ts_millis() if token.status != "OPEN": raise Unauthorized("Token status invalid") if cur_time >= int(token.expires): raise Unauthorized("Token expired") token_info = dict(actor_id=token.actor_id, expiry=token.expires, token=token, token_id=token_id) log.info("Authentication token %s resolved to actor %s, expiry %s", token_string, token.actor_id, token.expires) return token_info
def _create_token(self, actor_id='', start_time='', validity=0, token_type=TokenTypeEnum.ACTOR_AUTH): if not actor_id: raise BadRequest("Must provide argument: actor_id") actor_obj = self.rr.read(actor_id) if actor_obj.type_ != RT.ActorIdentity: raise BadRequest("Illegal type for argument actor_id") if type(validity) not in (int, long): raise BadRequest("Illegal type for argument validity") if validity <= 0 or validity > MAX_TOKEN_VALIDITY: raise BadRequest("Illegal value for argument validity") cur_time = get_ion_ts_millis() if not start_time: start_time = cur_time start_time = int(start_time) if start_time > cur_time: raise BadRequest( "Illegal value for start_time: Future values not allowed") if (start_time + 1000 * validity) < cur_time: raise BadRequest("Illegal value for start_time: Already expired") expires = str(start_time + 1000 * validity) token = self._generate_auth_token(actor_id, expires=expires, token_type=token_type) token_id = "token_%s" % token.token_string self.container.object_store.create(token, token_id) return token
def register_container(self, container_id, ts_event, state, container_info): if not container_id or not ts_event or not state: raise BadRequest("Invalid container registration") ts_event = int(ts_event) cc_obj = None if container_id not in self._containers: try: cc_objs, _ = self.rr.find_resources(restype=RT.CapabilityContainer, name=container_id, id_only=False) if cc_objs: cc_obj = cc_objs[0] except Exception: log.exception("Could not retrieve CapabilityContainer resource for %s", container_id) return with self._lock: if container_id not in self._containers: self._containers[container_id] = dict(cc_obj=cc_obj, container_id=container_id, ts_event=ts_event) container_entry = self._containers[container_id] if ts_event >= container_entry["ts_event"] or state == EE_STATE_TERMINATED: # This is filled for every new container_entry container_entry["ts_update"] = get_ion_ts_millis() container_entry["ts_event"] = ts_event container_entry["state"] = state container_entry["ee_info"] = container_entry["cc_obj"].execution_engine_config container_entry["ts_created"] = int(container_entry["cc_obj"].ts_created) container_entry["allocation"] = {} container_entry["dead_procs"] = {} if not self.preconditions_true.is_set(): self.check_preconditions()
def get_user(username, password, *args, **kwargs): """ Callback to assert username/password and establish a user session. Used in password authentication flow. Called only during token creation. NOTE: If the same username logs in multiple times (e.g. different windows), then the most recent session overrides all others, which still remain valid """ log.info("OAuth:get_user(%s)", username) if username and password: try: actor_id = ui_instance.idm_client.check_actor_credentials(username, password) actor_user = ui_instance.idm_client.read_actor_identity(actor_id) if actor_user.details.type_ != OT.UserIdentityDetails: log.warn("Bad identity details") return None # Create user session dict for ActorIdentity full_name = actor_user.details.contact.individual_names_given + " " + actor_user.details.contact.individual_name_family valid_until = int(get_ion_ts_millis() / 1000 + ui_instance.session_timeout) # Int with seconds user_session = {"actor_id": actor_id, "user_id": actor_id, "username": username, "full_name": full_name, "valid_until": valid_until} actor_user.session = user_session ui_instance.container.resource_registry.update(actor_user) flask.g.actor_id = actor_id return user_session except NotFound: pass return None
def _create_token(self, actor_id='', start_time='', validity=0, token_type=TokenTypeEnum.ACTOR_AUTH): if not actor_id: raise BadRequest("Must provide argument: actor_id") actor_obj = self.rr.read(actor_id) if actor_obj.type_ != RT.ActorIdentity: raise BadRequest("Illegal type for argument actor_id") if type(validity) not in (int, long): raise BadRequest("Illegal type for argument validity") if validity <= 0 or validity > MAX_TOKEN_VALIDITY: raise BadRequest("Illegal value for argument validity") cur_time = get_ion_ts_millis() if not start_time: start_time = cur_time start_time = int(start_time) if start_time > cur_time: raise BadRequest("Illegal value for start_time: Future values not allowed") if (start_time + 1000*validity) < cur_time: raise BadRequest("Illegal value for start_time: Already expired") expires = str(start_time + 1000*validity) token = self._generate_auth_token(actor_id, expires=expires, token_type=token_type) token_id = "token_%s" % token.token_string self.container.object_store.create(token, token_id) return token
def save_token(token, request, *args, **kwargs): """ Callback to persist newly created token. """ log.info("OAuth:save_token(%s)", token) current_time = get_ion_ts_millis() # Note: token["expires_in"] was initialized by the framework and is not correct expires = str(current_time + 1000 * ui_instance.session_timeout) # Str millis actor_id = flask.g.actor_id access_token_str = str(token["access_token"]) refresh_token_str = str(token["refresh_token"]) scopes = str(token["scope"]) # Access token token_obj = SecurityToken(token_type=TokenTypeEnum.OAUTH_ACCESS, token_string=access_token_str, expires=expires, status="OPEN", actor_id=actor_id, attributes=dict(access_token=access_token_str, refresh_token=refresh_token_str, scopes=scopes, client_id=flask.g.client_id, ts_created=current_time)) token_id = "access_token_%s" % access_token_str ui_instance.container.object_store.create(token_obj, token_id) # Refresh token token_obj = SecurityToken(token_type=TokenTypeEnum.OAUTH_REFRESH, token_string=refresh_token_str, expires=expires, status="OPEN", actor_id=actor_id, attributes=dict(access_token=access_token_str, refresh_token=refresh_token_str, scopes=scopes, client_id=flask.g.client_id, ts_created=current_time)) token_id = "refresh_token_%s" % refresh_token_str ui_instance.container.object_store.create(token_obj, token_id) if ui_instance.remember_user: # Store user_id and access_token within server session, so that a client can resume flask.session["access_token"] = access_token_str flask.session["actor_id"] = actor_id
def test_procs(self): # Start procs config = {} pid1 = self.container.spawn_process("hello1", __name__, "CoordinatedProcess", config=config) pid2 = self.container.spawn_process("hello2", __name__, "CoordinatedProcess", config=config) pid3 = self.container.spawn_process("hello3", __name__, "CoordinatedProcess", config=config) # Wait for them to be ready gevent.sleep(0.3) # Call service evt_pub = EventPublisher(event_type=OT.ResourceCommandEvent) hc = HelloServiceClient() end_time = get_ion_ts_millis() + 4000 counter = 0 while get_ion_ts_millis() < end_time: counter += 1 res = hc.hello("foo") evt_pub.publish_event(origin=str(counter)) gevent.sleep(random.random() * 0.1) # Wait for them to be finish gevent.sleep(0.3) # Wrap up self.container.terminate_process(pid1) self.container.terminate_process(pid2) self.container.terminate_process(pid3) evt_count = CoordinatedProcess.evt_count log.info("Counters: %s", evt_count) self.assertEqual(evt_count["total"], 3 * counter) master_evts = evt_count[pid1] + evt_count[pid2] + evt_count[pid3] self.assertLessEqual(master_evts, counter) if master_evts < counter: log.info("Lost %s events - no functioning master", counter - master_evts)
def is_valid(self, check_expiry=False): if not self._token_obj: return False if self._token_obj.status != "OPEN": return False if check_expiry and int(self._token_obj.expires) < get_ion_ts_millis(): return False return True
def load_token(access_token=None, refresh_token=None): """ Callback to retrieve token info from given token string. Called from verify_request. Expiration verification is done afterwards in the library. """ log.info("OAuth:load_token(access=%s, refresh=%s)", access_token, refresh_token) try: if access_token: token_id = str("access_token_%s" % access_token) with _token_lock: token_obj = ui_instance.container.object_store.read(token_id) token = OAuthTokenObj.from_security_token(token_obj) if not token.is_valid(): log.info("OAuth: client used invalid access token") return None flask.g.oauth_user = token.user flask.g.actor_id = token.user["actor_id"] if "noextend" not in request.headers.get("scion-session", "") and \ ui_instance.extend_session_timeout and token.is_valid(check_expiry=True): new_expires = get_ion_ts_millis() + 1000 * ui_instance.session_timeout if ui_instance.max_session_validity: # Make sure token does not exceed maximum validity new_expires = min(new_expires, token_obj.attributes.get("ts_created", 0) + 1000 * ui_instance.max_session_validity) if (ui_instance.session_timeout <= 120 and new_expires > int(token_obj.expires)) or \ (ui_instance.session_timeout > 120 and new_expires - 60000 > int(token_obj.expires)): # Only extend session if by 60 sec (unless session is very short as in testing) # This reduces the likelihood of an extension for i in xrange(3): token_obj.expires = str(new_expires) try: ui_instance.container.object_store.update(token_obj) break except Conflict: # Concurrency conflict: random wait, then get most recent object rev gevent.sleep(random.random() * 0.05 * (i+1)) # Add some random delays token_obj = ui_instance.container.object_store.read(token_id) token = OAuthTokenObj.from_security_token(token_obj) log.info("Access token extended for user=%s", token.user["actor_id"]) # IGNORE session in ActorIdentity return token elif refresh_token: token_id = str("refresh_token_%s" % refresh_token) token_obj = ui_instance.container.object_store.read(token_id) token = OAuthTokenObj.from_security_token(token_obj) if not token.is_valid(): log.info("OAuth: client used invalid refresh token") return None flask.g.oauth_user = token.user flask.g.actor_id = token.user["actor_id"] return token except NotFound: pass return None
def _check_lock(self): cur_time = get_ion_ts_millis() was_leader = self.is_leader() self._has_lock = self.container.directory.acquire_lock(self.scope, self._lock_timeout, self.instance_id) if self._has_lock: # We are the leader if not was_leader: log.info("Process %s is now the leader for '%s'", self.instance_id, self.scope) self._inform_acquire() self._lock_expires = cur_time + int(1000*self._lock_timeout)
def _check_lock(self): LOCK_TIMEOUT = 0.5 cur_time = get_ion_ts_millis() has_lock = self._is_master() self.has_lock = self.container.directory.acquire_lock("coord", LOCK_TIMEOUT, self.id) if self.has_lock: # We are the master if not has_lock: log.info("Process %s is now the master", self._proc_name) self.lock_expires = cur_time + int(1000*LOCK_TIMEOUT)
def _get_user_info(self, actor_id, username=None): actor_user = self.idm_client.read_identity_details(actor_id) if actor_user.type_ != OT.UserIdentityDetails: raise BadRequest("Bad identity details") full_name = actor_user.contact.individual_names_given + " " + actor_user.contact.individual_name_family valid_until = int(get_ion_ts_millis() / 1000 + self.session_timeout) set_auth(actor_id, username, full_name, valid_until=valid_until, roles=actor_user.contact.roles) user_info = get_auth() return user_info
def _check_lock(self): LOCK_TIMEOUT = 0.5 cur_time = get_ion_ts_millis() has_lock = self._is_master() self.has_lock = self.container.directory.acquire_lock( "coord", LOCK_TIMEOUT, self.id) if self.has_lock: # We are the master if not has_lock: log.info("Process %s is now the master", self._proc_name) self.lock_expires = cur_time + int(1000 * LOCK_TIMEOUT)
def _do_test_share_and_commitments(self, org_id): root_org = self.org_management_service.find_org() self.assertNotEqual(root_org, None) actor_obj = ActorIdentity(name="Test user") actor_id, _ = self.resource_registry.create(actor_obj) self.org_management_service.enroll_member(org_id, actor_id) inst_obj = TestInstrument(name="Test instrument") inst_id, _ = self.resource_registry.create(inst_obj) self.assertFalse(self.org_management_service.is_resource_acquired(resource_id=inst_id)) self.org_management_service.share_resource(org_id, inst_id) res_ids, _ = self.resource_registry.find_objects(org_id, PRED.hasResource, id_only=True) self.assertEquals(1, len(res_ids)) cmt_id = self.org_management_service.create_resource_commitment(org_id, actor_id, inst_id) self.assertTrue(self.org_management_service.is_resource_acquired(resource_id=inst_id)) self.assertFalse(self.org_management_service.is_resource_acquired_exclusively(resource_id=inst_id)) cmt_objs = self.org_management_service.find_commitments(org_id=org_id) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments(resource_id=inst_id) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments(actor_id=actor_id) self.assertEquals(1, len(cmt_objs)) res_objs = self.org_management_service.find_acquired_resources(org_id=org_id) self.assertEquals(1, len(res_objs)) res_objs = self.org_management_service.find_acquired_resources(actor_id=actor_id) self.assertEquals(1, len(res_objs)) cmt_id = self.org_management_service.create_resource_commitment(org_id, actor_id, inst_id, exclusive=True, expiration=get_ion_ts_millis()+1000) self.assertTrue(self.org_management_service.is_resource_acquired(resource_id=inst_id)) self.assertTrue(self.org_management_service.is_resource_acquired_exclusively(resource_id=inst_id)) cmt_objs = self.org_management_service.find_commitments(org_id=org_id, exclusive=True) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments(resource_id=inst_id, exclusive=True) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments(actor_id=actor_id, exclusive=True) self.assertEquals(1, len(cmt_objs)) self.org_management_service.unshare_resource(org_id, inst_id) res_ids, _ = self.resource_registry.find_objects(org_id, PRED.hasResource, id_only=True) self.assertEquals(0, len(res_ids)) self.resource_registry.delete(inst_id) self.resource_registry.delete(actor_id)
def _set_server_session(self, actor_id, username=None): """ Sets server session based on user_id and ActorIdentity. """ actor_user = self.idm_client.read_identity_details(actor_id) if actor_user.type_ != OT.UserIdentityDetails: raise BadRequest("Bad identity details") full_name = actor_user.contact.individual_names_given + " " + actor_user.contact.individual_name_family valid_until = int(get_ion_ts_millis() / 1000 + self.session_timeout) set_auth(actor_id, username, full_name, valid_until=valid_until, roles=actor_user.contact.roles) user_info = get_auth() return user_info
def _check_lock(self): cur_time = get_ion_ts_millis() was_leader = self.is_leader() self._has_lock = self.container.directory.acquire_lock( self.scope, self._lock_timeout, self.instance_id) if self._has_lock: # We are the leader if not was_leader: log.info("Process %s is now the leader for '%s'", self.instance_id, self.scope) self._inform_acquire() self._lock_expires = cur_time + int(1000 * self._lock_timeout)
def update_authentication_token(self, token=None): """Updates the given token. """ if not isinstance(token, SecurityToken): raise BadRequest("Illegal argument type: token") if token.token_type != TokenTypeEnum.ACTOR_AUTH: raise BadRequest("Argument token: Illegal type") cur_time = get_ion_ts_millis() token_exp = int(token.expires) if token_exp > cur_time + 1000*MAX_TOKEN_VALIDITY: raise BadRequest("Argument token: Maximum expiry extended") self.container.object_store.update(token)
def update_authentication_token(self, token=None): """Updates the given token. """ if not isinstance(token, SecurityToken): raise BadRequest("Illegal argument type: token") if token.token_type != TokenTypeEnum.ACTOR_AUTH: raise BadRequest("Argument token: Illegal type") cur_time = get_ion_ts_millis() token_exp = int(token.expires) if token_exp > cur_time + 1000 * MAX_TOKEN_VALIDITY: raise BadRequest("Argument token: Maximum expiry extended") self.container.object_store.update(token)
def test_procs(self): # Start procs config = {} pid1 = self.container.spawn_process("hello1", __name__, "CoordinatedProcess", config=config) pid2 = self.container.spawn_process("hello2", __name__, "CoordinatedProcess", config=config) pid3 = self.container.spawn_process("hello3", __name__, "CoordinatedProcess", config=config) # Wait for them to be ready gevent.sleep(0.3) # Call service evt_pub = EventPublisher(event_type=OT.ResourceCommandEvent) hc = HelloServiceClient() end_time = get_ion_ts_millis() + 4000 counter = 0 while get_ion_ts_millis() < end_time: counter += 1 res = hc.hello("foo") evt_pub.publish_event(origin=str(counter)) gevent.sleep(random.random()*0.1) # Wait for them to be finish gevent.sleep(0.3) # Wrap up self.container.terminate_process(pid1) self.container.terminate_process(pid2) self.container.terminate_process(pid3) evt_count = CoordinatedProcess.evt_count log.info("Counters: %s", evt_count) self.assertEqual(evt_count["total"], 3*counter) master_evts = evt_count[pid1] + evt_count[pid2] + evt_count[pid3] self.assertLessEqual(master_evts, counter) if master_evts < counter: log.info("Lost %s events - no functioning master", counter - master_evts)
def is_leader(self): """ Returns true if current instance is leader and lock did not expire """ if self._has_lock and get_ion_ts_millis() >= self._lock_expires: log.warn("Master lock '%s' held and expired by %s", self.scope, self.instance_id) self._inform_error("lock_expired") try: # Cannot call release_leader due to infinite recursion self.container.directory.release_lock(self.scope, lock_holder=self.instance_id) self._inform_release() except Exception: pass self._has_lock = False self._lock_expires = 0 return False return self._has_lock
def reset_password(self, username='', token_string='', new_password=''): actor_id = self.find_actor_identity_by_username(username) actor = self.rr.read(actor_id) if not actor.passwd_reset_token or actor.passwd_reset_token.status != 'OPEN': raise Unauthorized("Token status invalid") cur_time = get_ion_ts_millis() if cur_time >= int(actor.passwd_reset_token.expires): raise Unauthorized("Token expired") if actor.passwd_reset_token.token_string != token_string: raise Unauthorized("Password reset token_string does not match") # Update password self.set_user_password(username, new_password) # Invalidate token after success actor = self.rr.read(actor_id) # Read again, resource was updated in between actor.passwd_reset_token = None self.rr.update(actor)
def is_leader(self): """ Returns true if current instance is leader and lock did not expire """ if self._has_lock and get_ion_ts_millis() >= self._lock_expires: log.warn("Master lock '%s' held and expired by %s", self.scope, self.instance_id) self._inform_error("lock_expired") try: # Cannot call release_leader due to infinite recursion self.container.directory.release_lock( self.scope, lock_holder=self.instance_id) self._inform_release() except Exception: pass self._has_lock = False self._lock_expires = 0 return False return self._has_lock
def load_token(access_token=None, refresh_token=None): """ Callback to retrieve token info from given token string. Called from verify_request. Expiration verification is done afterwards in the library. """ log.info("OAuth:load_token(access=%s, refresh=%s)", access_token, refresh_token) try: if access_token: token_id = str("access_token_%s" % access_token) token_obj = ui_instance.container.object_store.read(token_id) token = OAuthTokenObj.from_security_token(token_obj) if not token.is_valid(): log.info("OAuth: client used invalid access token") return None flask.g.oauth_user = token.user flask.g.actor_id = token.user["actor_id"] if ui_instance.extend_session_timeout and token.is_valid(check_expiry=True): new_expires = get_ion_ts_millis() + 1000 * ui_instance.session_timeout if ui_instance.max_session_validity: # Make sure token does not exceed maximum validity new_expires = min(new_expires, token_obj.attributes.get("ts_created", 0) + 1000 * ui_instance.max_session_validity) if new_expires > int(token_obj.expires): token_obj.expires = str(new_expires) ui_instance.container.object_store.update(token_obj) token = OAuthTokenObj.from_security_token(token_obj) log.info("Access token extended for user=%s", token.user["actor_id"]) # IGNORE session in ActorIdentity return token elif refresh_token: token_id = str("refresh_token_%s" % refresh_token) token_obj = ui_instance.container.object_store.read(token_id) token = OAuthTokenObj.from_security_token(token_obj) if not token.is_valid(): log.info("OAuth: client used invalid refresh token") return None flask.g.oauth_user = token.user flask.g.actor_id = token.user["actor_id"] return token except NotFound: pass return None
def reset_password(self, username='', token_string='', new_password=''): actor_id = self.find_actor_identity_by_username(username) actor = self.rr.read(actor_id) if not actor.passwd_reset_token or actor.passwd_reset_token.status != 'OPEN': raise Unauthorized("Token status invalid") cur_time = get_ion_ts_millis() if cur_time >= int(actor.passwd_reset_token.expires): raise Unauthorized("Token expired") if actor.passwd_reset_token.token_string != token_string: raise Unauthorized("Password reset token_string does not match") # Update password self.set_user_password(username, new_password) # Invalidate token after success actor = self.rr.read( actor_id) # Read again, resource was updated in between actor.passwd_reset_token = None self.rr.update(actor)
def register_container(self, container_id, ts_event, state, container_info): if not container_id or not ts_event or not state: raise BadRequest("Invalid container registration") ts_event = int(ts_event) cc_obj = None if container_id not in self._containers: try: cc_objs, _ = self.rr.find_resources( restype=RT.CapabilityContainer, name=container_id, id_only=False) if cc_objs: cc_obj = cc_objs[0] except Exception: log.exception( "Could not retrieve CapabilityContainer resource for %s", container_id) return with self._lock: if container_id not in self._containers: self._containers[container_id] = dict( cc_obj=cc_obj, container_id=container_id, ts_event=ts_event) container_entry = self._containers[container_id] if ts_event >= container_entry[ "ts_event"] or state == EE_STATE_TERMINATED: # This is filled for every new container_entry container_entry["ts_update"] = get_ion_ts_millis() container_entry["ts_event"] = ts_event container_entry["state"] = state container_entry["ee_info"] = container_entry[ "cc_obj"].execution_engine_config container_entry["ts_created"] = int( container_entry["cc_obj"].ts_created) container_entry["allocation"] = {} container_entry["dead_procs"] = {} if not self.preconditions_true.is_set(): self.check_preconditions()
def create_authentication_token(self, actor_id='', start_time='', validity=0): """Create an authentification token for provided actor id with a given start time and validity. start_time defaults to current time if empty and uses a system timestamp. validity is in seconds and must be set. @param actor_id str @param start_time str @param validity int @retval token_string str @throws BadRequest Illegal parameter type of value @throws NotFound Object not found """ if not actor_id: raise BadRequest("Must provide argument: actor_id") actor_obj = self.clients.resource_registry.read(actor_id) if actor_obj.type_ != RT.ActorIdentity: raise BadRequest("Illegal type for argument actor_id") if type(validity) not in (int, long): raise BadRequest("Illegal type for argument validity") if validity <= 0 or validity > MAX_TOKEN_VALIDITY: raise BadRequest("Illegal value for argument validity") cur_time = get_ion_ts_millis() if not start_time: start_time = cur_time start_time = int(start_time) if start_time > cur_time: raise BadRequest( "Illegal value for start_time: Future values not allowed") if (start_time + 1000 * validity) < cur_time: raise BadRequest("Illegal value for start_time: Already expired") expires = str(start_time + 1000 * validity) token = self._generate_auth_token(actor_id, expires=expires) token_id = "token_%s" % token.token_string self.container.object_store.create(token, token_id) return token.token_string
def logout(self): try: access_token = get_req_bearer_token() or flask.session.get("access_token", None) if access_token: try: # Invalidate access token token_id = str("access_token_%s" % access_token) token_obj = ui_instance.container.object_store.read(token_id) token_obj.status = "CANCELLED" token_obj.attributes["cancel_ts"] = get_ion_ts_millis() token_obj.attributes["cancel_msg"] = "User logout" ui_instance.container.object_store.update(token_obj) log.info("Invalidated stored access token for user=%s", token_obj.actor_id) except NotFound: pass except Exception: log.exception("Error invalidating access token") clear_auth() return build_json_response("OK") except Exception: return build_json_error()
def get_user(username, password, *args, **kwargs): # Required for password credential authentication log.info("OAuth:get_user(%s)", username) if username and password: try: actor_id = ui_instance.idm_client.check_actor_credentials(username, password) actor_user = ui_instance.idm_client.read_actor_identity(actor_id) if actor_user.details.type_ != OT.UserIdentityDetails: log.warn("Bad identity details") return None full_name = actor_user.details.contact.individual_names_given + " " + actor_user.details.contact.individual_name_family valid_until = int(get_ion_ts_millis() / 1000 + ui_instance.session_timeout) user_session = {"actor_id": actor_id, "user_id": actor_id, "username": username, "full_name": full_name, "valid_until": valid_until} actor_user.session = user_session ui_instance.container.resource_registry.update(actor_user) flask.g.actor_id = actor_id return user_session except NotFound: pass return None
def download_asset_data(self, asset_id='', data_format='', data_filter=None): asset_obj = self._validate_resource_id("asset_id", asset_id, RT.Instrument) dataset_objs, _ = self.rr.find_objects(asset_id, PRED.hasDataset, RT.Dataset, id_only=False) if not dataset_objs: raise BadRequest("Could not find dataset") dataset_obj = dataset_objs[0] if data_format and data_format != "hdf5": raise BadRequest("Unsupported download data format") from ion.data.persist.hdf5_dataset import DatasetHDF5Persistence persistence = DatasetHDF5Persistence(dataset_obj._id, dataset_obj.schema_definition, "hdf5") data_filter1 = dict(transpose_time=True, time_format="unix_millis", max_rows=100000, start_time=get_ion_ts_millis() - 86400000) data_filter1.update(data_filter or {}) temp_filename = persistence.get_data_copy(data_filter=data_filter1) resp_hdrs = { "Content-Disposition": 'attachment; filename="ds_%s.hdf5"' % asset_obj._id } mr = MediaResponse(media_mimetype="application/octet-stream", body=temp_filename, internal_encoding="filename", response_headers=resp_hdrs) return mr
def download_asset_data(self, asset_id='', data_format='', data_filter=None): asset_obj = self._validate_resource_id("asset_id", asset_id, RT.Instrument) dataset_objs, _ = self.rr.find_objects(asset_id, PRED.hasDataset, RT.Dataset, id_only=False) if not dataset_objs: raise BadRequest("Could not find dataset") dataset_obj = dataset_objs[0] if data_format and data_format != "hdf5": raise BadRequest("Unsupported download data format") from ion.data.persist.hdf5_dataset import DatasetHDF5Persistence persistence = DatasetHDF5Persistence(dataset_obj._id, dataset_obj.schema_definition, "hdf5") data_filter1 = dict(transpose_time=True, time_format="unix_millis", max_rows=100000, start_time=get_ion_ts_millis() - 86400000) data_filter1.update(data_filter or {}) temp_filename = persistence.get_data_copy(data_filter=data_filter1) resp_hdrs = {"Content-Disposition": 'attachment; filename="ds_%s.hdf5"' % asset_obj._id} mr = MediaResponse(media_mimetype="application/octet-stream", body=temp_filename, internal_encoding="filename", response_headers=resp_hdrs) return mr
def save_token(token, request, *args, **kwargs): log.info("OAuth:save_token=%s", token) expires = str(get_ion_ts_millis() + 1000*token["expires_in"]) actor_id = flask.g.actor_id access_token_str = str(token["access_token"]) refresh_token_str = str(token["refresh_token"]) scopes = str(token["scope"]) # Access token token_obj = SecurityToken(token_type=TokenTypeEnum.OAUTH_ACCESS, token_string=access_token_str, expires=expires, status="OPEN", actor_id=actor_id, attributes=dict(access_token=access_token_str, refresh_token=refresh_token_str, scopes=scopes, client_id=flask.g.client_id)) token_id = "access_token_%s" % access_token_str ui_instance.container.object_store.create(token_obj, token_id) # Refresh token token_obj = SecurityToken(token_type=TokenTypeEnum.OAUTH_REFRESH, token_string=refresh_token_str, expires=expires, status="OPEN", actor_id=actor_id, attributes=dict(access_token=access_token_str, refresh_token=refresh_token_str, scopes=scopes, client_id=flask.g.client_id)) token_id = "refresh_token_%s" % refresh_token_str ui_instance.container.object_store.create(token_obj, token_id)
def create_authentication_token(self, actor_id='', start_time='', validity=0): """Create an authentification token for provided actor id with a given start time and validity. start_time defaults to current time if empty and uses a system timestamp. validity is in seconds and must be set. @param actor_id str @param start_time str @param validity int @retval token_string str @throws BadRequest Illegal parameter type of value @throws NotFound Object not found """ if not actor_id: raise BadRequest("Must provide argument: actor_id") actor_obj = self.clients.resource_registry.read(actor_id) if actor_obj.type_ != RT.ActorIdentity: raise BadRequest("Illegal type for argument actor_id") if type(validity) not in (int, long): raise BadRequest("Illegal type for argument validity") if validity <= 0 or validity > MAX_TOKEN_VALIDITY: raise BadRequest("Illegal value for argument validity") cur_time = get_ion_ts_millis() if not start_time: start_time = cur_time start_time = int(start_time) if start_time > cur_time: raise BadRequest("Illegal value for start_time: Future values not allowed") if (start_time + 1000*validity) < cur_time: raise BadRequest("Illegal value for start_time: Already expired") expires = str(start_time + 1000*validity) token = self._generate_auth_token(actor_id, expires=expires) token_id = "token_%s" % token.token_string self.container.object_store.create(token, token_id) return token.token_string
def test_auth_tokens(self): # Note: test of service gateway token functionality is in SGS test rr = self.resource_registry actor_identity_obj = IonObject("ActorIdentity", {"name": self.subject}) actor_id = self.identity_management_service.create_actor_identity(actor_identity_obj) user_info_obj = IonObject("UserInfo", {"name": "Foo"}) user_info_id = self.identity_management_service.create_user_info(actor_id, user_info_obj) token_str = self.identity_management_service.create_authentication_token(actor_id, validity=10000) self.assertIsInstance(token_str, str) self.assertGreaterEqual(len(token_str), 25) token_info = self.identity_management_service.check_authentication_token(token_str) self.assertEquals(token_info["actor_id"], actor_id) token_info = self.identity_management_service.check_authentication_token(token_str) self.assertGreaterEqual(int(token_info["expiry"]), get_ion_ts_millis()) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id="", validity=10000) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(user_info_id, validity=10000) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, validity="FOO") with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, validity=-200) cur_time = get_ion_ts_millis() with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, start_time=str(cur_time-100000), validity=50) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, validity=35000000) with self.assertRaises(NotFound): self.identity_management_service.check_authentication_token("UNKNOWN") token_str2 = self.identity_management_service.create_authentication_token(actor_id, validity=1) token_info = self.identity_management_service.check_authentication_token(token_str2) gevent.sleep(1.1) with self.assertRaises(Unauthorized): self.identity_management_service.check_authentication_token(token_str2) token = self.identity_management_service.read_authentication_token(token_str2) token.expires = str(cur_time + 5000) self.identity_management_service.update_authentication_token(token) token_info = self.identity_management_service.check_authentication_token(token_str2) token_str3 = self.identity_management_service.create_authentication_token(actor_id, validity=2) token_info = self.identity_management_service.check_authentication_token(token_str3) self.identity_management_service.invalidate_authentication_token(token_str3) with self.assertRaises(Unauthorized): self.identity_management_service.check_authentication_token(token_str3) token = self.identity_management_service.read_authentication_token(token_str3) self.assertEquals(token.token_string, token_str3) self.assertIn(token_str3, token._id) token.status = "OPEN" self.identity_management_service.update_authentication_token(token) token_info = self.identity_management_service.check_authentication_token(token_str3) # Cleanup self.identity_management_service.delete_user_info(user_info_id) self.identity_management_service.delete_actor_identity(actor_id)
def _do_test_auth_tokens(self, actor_id): # Note: test of service gateway token functionality is in SGS test token_str = self.identity_management_service.create_authentication_token( actor_id, validity=10000) self.assertIsInstance(token_str, str) self.assertGreaterEqual(len(token_str), 25) token_info = self.identity_management_service.check_authentication_token( token_str) self.assertEquals(token_info["actor_id"], actor_id) token_info = self.identity_management_service.check_authentication_token( token_str) self.assertGreaterEqual(int(token_info["expiry"]), get_ion_ts_millis()) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token( actor_id="", validity=10000) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token( actor_id, validity="FOO") with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token( actor_id, validity=-200) cur_time = get_ion_ts_millis() with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token( actor_id, start_time=str(cur_time - 100000), validity=50) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token( actor_id, validity=35000000) with self.assertRaises(NotFound): self.identity_management_service.check_authentication_token( "UNKNOWN") token_str2 = self.identity_management_service.create_authentication_token( actor_id, validity=1) token_info = self.identity_management_service.check_authentication_token( token_str2) gevent.sleep(1.1) with self.assertRaises(Unauthorized): self.identity_management_service.check_authentication_token( token_str2) token = self.identity_management_service.read_authentication_token( token_str2) token.expires = str(cur_time + 5000) self.identity_management_service.update_authentication_token(token) token_info = self.identity_management_service.check_authentication_token( token_str2) token_str3 = self.identity_management_service.create_authentication_token( actor_id, validity=2) token_info = self.identity_management_service.check_authentication_token( token_str3) self.identity_management_service.invalidate_authentication_token( token_str3) with self.assertRaises(Unauthorized): self.identity_management_service.check_authentication_token( token_str3) token = self.identity_management_service.read_authentication_token( token_str3) self.assertEquals(token.token_string, token_str3) self.assertIn(token_str3, token._id) token.status = "OPEN" self.identity_management_service.update_authentication_token(token) token_info = self.identity_management_service.check_authentication_token( token_str3)
def _is_master(self): return self.has_lock and get_ion_ts_millis() < self.lock_expires
def _do_test_share_and_commitments(self, org_id): root_org = self.org_management_service.find_org() self.assertNotEqual(root_org, None) actor_obj = ActorIdentity(name="Test user") actor_id, _ = self.resource_registry.create(actor_obj) self.org_management_service.enroll_member(org_id, actor_id) inst_obj = TestInstrument(name="Test instrument") inst_id, _ = self.resource_registry.create(inst_obj) self.assertFalse( self.org_management_service.is_resource_acquired( resource_id=inst_id)) self.org_management_service.share_resource(org_id, inst_id) res_ids, _ = self.resource_registry.find_objects(org_id, PRED.hasResource, id_only=True) self.assertEquals(1, len(res_ids)) cmt_id = self.org_management_service.create_resource_commitment( org_id, actor_id, inst_id) self.assertTrue( self.org_management_service.is_resource_acquired( resource_id=inst_id)) self.assertFalse( self.org_management_service.is_resource_acquired_exclusively( resource_id=inst_id)) cmt_objs = self.org_management_service.find_commitments(org_id=org_id) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments( resource_id=inst_id) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments( actor_id=actor_id) self.assertEquals(1, len(cmt_objs)) res_objs = self.org_management_service.find_acquired_resources( org_id=org_id) self.assertEquals(1, len(res_objs)) res_objs = self.org_management_service.find_acquired_resources( actor_id=actor_id) self.assertEquals(1, len(res_objs)) cmt_id = self.org_management_service.create_resource_commitment( org_id, actor_id, inst_id, exclusive=True, expiration=get_ion_ts_millis() + 1000) self.assertTrue( self.org_management_service.is_resource_acquired( resource_id=inst_id)) self.assertTrue( self.org_management_service.is_resource_acquired_exclusively( resource_id=inst_id)) cmt_objs = self.org_management_service.find_commitments(org_id=org_id, exclusive=True) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments( resource_id=inst_id, exclusive=True) self.assertEquals(1, len(cmt_objs)) cmt_objs = self.org_management_service.find_commitments( actor_id=actor_id, exclusive=True) self.assertEquals(1, len(cmt_objs)) self.org_management_service.unshare_resource(org_id, inst_id) res_ids, _ = self.resource_registry.find_objects(org_id, PRED.hasResource, id_only=True) self.assertEquals(0, len(res_ids)) self.resource_registry.delete(inst_id) self.resource_registry.delete(actor_id)
def _do_test_auth_tokens(self, actor_id): # Note: test of service gateway token functionality is in SGS test token_str = self.identity_management_service.create_authentication_token(actor_id, validity=10000) self.assertIsInstance(token_str, str) self.assertGreaterEqual(len(token_str), 25) token_info = self.identity_management_service.check_authentication_token(token_str) self.assertEquals(token_info["actor_id"], actor_id) token_info = self.identity_management_service.check_authentication_token(token_str) self.assertGreaterEqual(int(token_info["expiry"]), get_ion_ts_millis()) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id="", validity=10000) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, validity="FOO") with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, validity=-200) cur_time = get_ion_ts_millis() with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, start_time=str(cur_time-100000), validity=50) with self.assertRaises(BadRequest): self.identity_management_service.create_authentication_token(actor_id, validity=35000000) with self.assertRaises(NotFound): self.identity_management_service.check_authentication_token("UNKNOWN") token_str2 = self.identity_management_service.create_authentication_token(actor_id, validity=1) token_info = self.identity_management_service.check_authentication_token(token_str2) gevent.sleep(1.1) with self.assertRaises(Unauthorized): self.identity_management_service.check_authentication_token(token_str2) token = self.identity_management_service.read_authentication_token(token_str2) token.expires = str(cur_time + 5000) self.identity_management_service.update_authentication_token(token) token_info = self.identity_management_service.check_authentication_token(token_str2) token_str3 = self.identity_management_service.create_authentication_token(actor_id, validity=2) token_info = self.identity_management_service.check_authentication_token(token_str3) self.identity_management_service.invalidate_authentication_token(token_str3) with self.assertRaises(Unauthorized): self.identity_management_service.check_authentication_token(token_str3) token = self.identity_management_service.read_authentication_token(token_str3) self.assertEquals(token.token_string, token_str3) self.assertIn(token_str3, token._id) token.status = "OPEN" self.identity_management_service.update_authentication_token(token) token_info = self.identity_management_service.check_authentication_token(token_str3)