def invoke_lambda(function_name, auth_token, body, trigger_type=constants.TriggerType.ASYNC.value): if not body: body = {} body['Authorization'] = auth_token client = boto3.client('lambda') response = client.invoke( FunctionName=function_name, InvocationType='Event' if trigger_type == constants.TriggerType.ASYNC.value else 'RequestResponse', LogType='None', Payload=bytes(json.dumps(body))) response_payload = {"statusCode": 200, "body": ""} if trigger_type == constants.TriggerType.SYNC.value: response_payload = json.loads( response['Payload'].read().decode("utf-8")) Logger().info("Response from sync lambda invocation is - {}".format( response_payload)) if "errorMessage" in response_payload: return ResponseMessage(500, response_payload['errorMessage']) return ResponseMessage(response_payload['statusCode'], None, response_payload['body'])
def delete_user_from_group(auth_token, group_email, user_email): directory_service = gutils.get_directory_service(auth_token) Logger().info("Initiating removal of user {} from group {} ...".format(user_email, group_email)) try: response = directory_service.members().delete(groupKey=group_email, memberKey=user_email).execute() return ResponseMessage(200, None, response) except Exception as ex: content = json.loads(ex.content) if ex.content else {} return ResponseMessage(500, None, content)
def receive_notification(auth_token, payload): event_type = fetch_event_type(payload) if event_type: handler = get_handler(event_type) handler.process_activity(auth_token, payload["body"], event_type) return ResponseMessage(202, "Notification handled successfully") else: return ResponseMessage( 400, "Unable to fetch event type from event payload")
def initiate_action(auth_token, action_payload): try: action_key = action_payload['key'] initiated_by = action_payload['initiated_by'] action_parameters = action_payload['parameters'] datasource_id = action_payload[ 'datasource_id'] if 'datasource_id' in action_payload else 'MANUAL' db_session = db_connection().get_session() login_user_info = db_session.query(LoginUser).filter( LoginUser.auth_token == auth_token).first() domain_id = login_user_info.domain_id action_config = get_action(action_key) if not action_config or not validate_action_parameters( action_config, action_parameters): return ResponseMessage( 400, "Failed to execute action - Validation failed") log_id = action_payload[ 'log_id'] if 'log_id' in action_payload else None if log_id: log_entry = db_session.query(AuditLog).filter( and_(AuditLog.log_id == log_id)).first() else: log_entry = audit_action(domain_id, datasource_id, initiated_by, action_config, action_parameters) execution_status = execute_action(auth_token, domain_id, datasource_id, action_config, action_payload, log_entry) db_connection().commit() Logger().info("initiate_action : response body - {}".format( execution_status.get_response_body())) response_body = json.loads( json.dumps(execution_status.get_response_body())) response_body['id'] = log_entry.log_id if execution_status.response_code == constants.ACCEPTED_STATUS_CODE: action_payload['log_id'] = log_entry.log_id messaging.trigger_post_event(urls.INITIATE_ACTION_PATH, auth_token, None, action_payload) return ResponseMessage(execution_status.response_code, None, response_body) except Exception as e: Logger().exception( "Exception occurred while initiating action using payload " + str(action_payload)) return ResponseMessage(500, "Failed to execute action - {}".format(e))
def add_user_to_group(auth_token, group_email, user_email): directory_service = gutils.get_directory_service(auth_token) body = { "kind": "admin#directory#member", "email": user_email, "role": "MEMBER" } Logger().info("Initiating addition of user {} to group {} ...".format(user_email, group_email)) try: response = directory_service.members().insert(groupKey=group_email, body=body).execute() return ResponseMessage(200, None, response) except Exception as ex: content = json.loads(ex.content) if ex.content else {} return ResponseMessage(500, None, content)
def trigger_post_event_with_headers( endpoint, auth_token, query_params, headers, body, service_name="core", trigger_type=constants.TriggerType.ASYNC.value): result = None if constants.DEPLOYMENT_ENV == 'local': session = FuturesSession() endpoint = _add_query_params_to_url(endpoint, query_params) Logger().info("Making a POST request on the following url - " + str(endpoint)) response = utils.post_call_with_authorization_header( session, endpoint, auth_token, body, headers) if trigger_type == constants.TriggerType.SYNC.value: api_response = response.result() result = ResponseMessage(api_response.status_code, None, json.loads(api_response.content)) else: body = _add_query_params_to_body(body, query_params) body = _add_headers_to_body(body, headers) endpoint = service_name + "-" + \ constants.DEPLOYMENT_ENV + "-post-" + slugify(endpoint) Logger().info( "Making a POST lambda invoke on the following function - " + str(endpoint)) result = aws_utils.invoke_lambda(endpoint, auth_token, body, trigger_type) return result
def export_to_csv(auth_token, payload): if not 'is_async' in payload: payload['is_async'] = True messaging.trigger_post_event(urls.USERS_EXPORT, auth_token, None, payload) return ResponseMessage(202, "Your download request is in process, you shall receive an email with the download link soon...") else: write_to_csv(auth_token, payload)
def delete_permissions(auth_token, permissions, owner_email, initiated_by_email, datasource_id): drive_service = gutils.get_gdrive_service(auth_token, owner_email) updated_permissions = {} is_success = True exception_messages = "" for permission in permissions: resource_id = permission['resource_id'] permission_id = permission['permission_id'] retry = 0 while True: retry += 1 try: drive_service.permissions().delete(fileId=resource_id, quotaUser= owner_email[0:41], permissionId=permission_id).execute() if not permission['resource_id'] in updated_permissions: updated_permissions[permission['resource_id']] = [permission] else: updated_permissions[permission['resource_id']].append(permission) break except HttpError as ex: if ex.resp.status == 404: Logger().info("Permission not found : permission - {} : ex - {}".format(permission, ex)) if not permission['resource_id'] in updated_permissions: updated_permissions[permission['resource_id']] = [permission] else: updated_permissions[permission['resource_id']].append(permission) break elif ex.resp.status == 403 and retry < 6: #API limit reached, so retry after few seconds for 5 times sleep_secs = min(64, (2 ** retry)) + (random.randint(0, 1000) / 1000.0) Logger().warn("API limit reached while deleting the permission in gsuite, will retry after {} secs: {}".format(sleep_secs, permission)) time.sleep(sleep_secs) elif ex.resp.status == 500 and retry < 6: sleep_secs = min(64, (2 ** retry)) + (random.randint(0, 1000) / 1000.0) Logger().warn("Backend Error while deleting the permission in gsuite, will retry after {} secs: {}".format( sleep_secs, permission)) time.sleep(sleep_secs) else: Logger().exception("Exception occurred while deleting permissions in gsuite : permission - {}".format(permission)) is_success = False if ex.content: content = json.loads(ex.content) exception_messages += content['error']['message'] if content['error']['message'] else "Exception occurred while deleting permissions in gsuite" break except Exception as ex: Logger().exception("Exception occurred while deleting permissions in gsuite : ex - {}".format(ex)) is_success = False exception_messages += "Exception occurred while deleting permissions in gsuite" break try: Logger().info("updated_permissions to be deleted from db - {}".format(updated_permissions)) delete_resource_permission(initiated_by_email, datasource_id, updated_permissions) except Exception: Logger().exception("Exception occurred while removing permission from db") is_success = False exception_messages += "Exception occurred while removing permission from db" return ResponseMessage(200 if is_success else 500, exception_messages)
def transfer_ownership(auth_token, old_owner_email, new_owner_email): datatransfer_service = gutils.get_gdrive_datatransfer_service(auth_token) Logger().info("Initiating data transfer...") applicationDataTransfers = get_applicationDataTransfers_for_gdrive(datatransfer_service) directory_service = gutils.get_directory_service(auth_token) old_user_id = directory_service.users().get(userKey=old_owner_email).execute() old_user_id = old_user_id.get('id') new_user_id = directory_service.users().get(userKey=new_owner_email).execute() new_user_id = new_user_id.get('id') transfersResource = {"oldOwnerUserId": old_user_id, "newOwnerUserId": new_user_id, "applicationDataTransfers": applicationDataTransfers} try: response = datatransfer_service.transfers().insert(body=transfersResource).execute() Logger().info(str(response)) return ResponseMessage(200, None, response) except Exception as ex: content = json.loads(ex.content) if ex.content else {} return ResponseMessage(500, None, content)
def update_permissions(auth_token, permissions, owner_email, initiated_by_email, datasource_id): drive_service = gutils.get_gdrive_service(auth_token, owner_email) updated_permissions = {} deleted_permissions = {} is_success = True exception_messages = "" for permission in permissions: resource_id = permission['resource_id'] permission_id = permission['permission_id'] role = permission['permission_type'] update_permission_object = { "role": role, } try: drive_service.permissions().update(fileId=resource_id, body=update_permission_object, quotaUser= owner_email[0:41], permissionId=permission_id, transferOwnership=True if role == 'owner' else False).execute() if not permission['resource_id'] in updated_permissions: updated_permissions[permission['resource_id']] = [permission] else: updated_permissions[permission['resource_id']].append(permission) except HttpError as e: if e.resp.status == 404: Logger().info("Permission not found in gsuite, hence delete from db") if not permission['resource_id'] in deleted_permissions: deleted_permissions[permission['resource_id']] = [permission] else: deleted_permissions[permission['resource_id']].append(permission) else: Logger().exception("HttpError Exception occurred while updating permissions in gsuite ; {}".format(e)) is_success = False if e.content: content = json.loads(e.content) exception_messages += content['error']['message'] if content['error']['message'] else "Exception occurred while updating permissions in gsuite" except Exception as ex: Logger().exception("Exception occurred while updating permissions in gsuite : {}".format(ex)) is_success = False exception_messages += "Exception occurred while updating permissions in gsuite" try: update_resource_permissions(initiated_by_email, datasource_id, updated_permissions) if len(deleted_permissions) > 0: delete_resource_permission(initiated_by_email, datasource_id, deleted_permissions) except Exception as ex: Logger().exception("Exception occurred while updating permission from db : {}".format(ex)) is_success = False exception_messages += "Exception occurred while updating permission from db" return ResponseMessage(200 if is_success else 500, exception_messages)
def add_permissions(auth_token, permissions, owner_email, initiated_by_email, datasource_id, domain_id): is_success = True exception_messages = "" drive_service = gutils.get_gdrive_service(auth_token, owner_email) for permission in permissions: resource_id = permission['resource_id'] role = permission['permission_type'] email = permission['email'] email_type = "user" db_session = db_connection().get_session() existing_group = db_session.query(DomainUser).filter( and_(DomainUser.datasource_id == permission['datasource_id'], DomainUser.email == email)).first() if existing_group: email_type = "group" add_permission_object = { "role": role, "type": email_type, "emailAddress": email } request = drive_service.permissions().create(fileId=resource_id, body=add_permission_object, quotaUser= owner_email[0:41], transferOwnership=True if role == 'owner' else False, fields='id, emailAddress, type, kind, displayName') try: # check for existing permission only if action role is of 'owner' response = request.execute() permission['displayName'] = response['displayName'] if 'displayName' in response else "" Logger().info("Add permission response from google is - {}".format(response)) permission['permission_id'] = response['id'] add_new_permission_to_db(permission, resource_id, datasource_id, initiated_by_email, role, domain_id) except Exception as ex: Logger().exception("Exception occurred while adding a new permission") is_success = False if ex.content: content = json.loads(ex.content) exception_messages += content['error']['message'] if content['error']['message'] else "Exception occurred while adding new permission to db" else: exception_messages += "Exception occurred while adding new permission to db" return ResponseMessage(200 if is_success else 500, exception_messages)
def delete_permissions(auth_token, permissions, user_email, initiated_by_email, datasource_id): #Remove the collaborator from the repository github_client = github_utils.get_github_client(datasource_id) db_session = db_connection().get_session() repo_by_id = {} updated_permissions = {} for permission in permissions: repo_id = permission["resource_id"] if not repo_id in repo_by_id: db_repo = db_session.query(Resource).filter( and_(Resource.datasource_id == permission["datasource_id"], Resource.resource_id == repo_id)).first() repo = github_client.get_repo(db_repo.resource_name) repo_by_id[repo_id] = repo repo = repo_by_id[repo_id] for collaborator in repo.get_collaborators(): collaborator_obj = collaborator.raw_data if str(collaborator_obj["id"]) == permission["permission_id"]: #Delete the collaborator repo.remove_from_collaborators(collaborator) if not permission['resource_id'] in updated_permissions: updated_permissions[permission['resource_id']] = [ permission ] else: updated_permissions[permission['resource_id']].append( permission) break try: print updated_permissions action_utils.delete_resource_permission(initiated_by_email, datasource_id, updated_permissions) except Exception: Logger().exception( "Exception occurred while removing permission from db") is_success = False return ResponseMessage(200, "")
def create_watch_report(auth_token, datasource_id, action_payload, log_entry): action_parameters = action_payload['parameters'] user_email = str(action_parameters['user_email']) form_input = {} form_input['name'] = "Activity for " + user_email form_input['description'] = "Activity for " + user_email form_input['frequency'] = "cron(0 9 ? * 2 *)" form_input['receivers'] = action_payload['initiated_by'] form_input['report_type'] = "Activity" form_input['selected_entity_type'] = "user" form_input['selected_entity'] = user_email form_input['selected_entity_name'] = user_email form_input['is_active'] = 0 form_input['datasource_id'] = datasource_id messaging.trigger_post_event(urls.GET_SCHEDULED_REPORT_PATH, auth_token, None, form_input) log_entry.status = action_constants.ActionStatus.SUCCESS.value log_entry.message = 'Action completed successfully' return ResponseMessage(201, "Watch report created for {}".format(user_email))
def create_alerts(auth_token, payload): db_session = db_connection().get_session() if payload: alert = Alert() last_update_time = datetime.datetime.utcnow() alert.alert_id = str(uuid.uuid4()) alert.datasource_id = payload["datasource_id"] alert.name = payload["name"] alert.isOpen = True alert.number_of_violations = 1 alert.last_updated = last_update_time alert.created_at = last_update_time alert.severity = payload["severity"] alert.policy_id = payload["policy_id"] payload["payload"]["policy_name"] = payload["name"] alert.payload = json.dumps(payload["payload"]) alert.description_template = payload["description_template"] db_session.add(alert) db_connection().commit() return alert return ResponseMessage(400, 'Bad Request')
def execute_action(auth_token, domain_id, datasource_id, action_config, action_payload, log_entry): action_parameters = action_payload['parameters'] response_msg = '' action_key = action_config["key"] # Watch report action if action_key == action_constants.ActionNames.WATCH_ALL_ACTION_FOR_USER.value: response_msg = create_watch_report(auth_token, datasource_id, action_payload, log_entry) # Trigger mail for cleaning files elif action_key == action_constants.ActionNames.NOTIFY_USER_FOR_CLEANUP.value: user_email = action_parameters['user_email'] full_name = action_parameters['full_name'] initiated_by = action_payload['initiated_by'] status_message = "Notification sent to {} for cleanUp".format( user_email) log_entry.status = action_constants.ActionStatus.SUCCESS.value status_code = 200 if not adya_emails.send_clean_files_email(datasource_id, user_email, full_name, initiated_by): status_message = "Sending Notification failed for {}".format( user_email) log_entry.status = action_constants.ActionStatus.FAILED.value status_code = 400 log_entry.message = status_message response_msg = ResponseMessage(status_code, status_message) # Directory change actions elif action_key == action_constants.ActionNames.REMOVE_USER_FROM_GROUP.value or action_key == action_constants.ActionNames.ADD_USER_TO_GROUP.value: response_msg = modify_group_membership(auth_token, datasource_id, action_key, action_parameters, log_entry) # Transfer ownership # part of batch action elif action_key == action_constants.ActionNames.TRANSFER_OWNERSHIP.value: response_msg = transfer_ownership(auth_token, datasource_id, action_key, action_parameters, log_entry) # Bulk permission change actions for user elif action_key == action_constants.ActionNames.MAKE_ALL_FILES_PRIVATE.value: user_email = action_parameters['user_email'] initiated_by = action_payload['initiated_by'] response_msg = update_access_for_owned_files(auth_token, domain_id, datasource_id, user_email, initiated_by, "ALL", log_entry, action_key) elif action_key == action_constants.ActionNames.REMOVE_EXTERNAL_ACCESS.value: user_email = action_parameters['user_email'] initiated_by = action_payload['initiated_by'] response_msg = update_access_for_owned_files( auth_token, domain_id, datasource_id, user_email, initiated_by, constants.EntityExposureType.EXTERNAL.value, log_entry, action_key) elif action_key == action_constants.ActionNames.REMOVE_ALL_ACCESS_FOR_USER.value: user_email = action_parameters['user_email'] initiated_by = action_payload['initiated_by'] response_msg = remove_all_permissions_for_user(auth_token, domain_id, datasource_id, user_email, initiated_by, log_entry, action_key) # Bulk permission change actions for resource elif action_key == action_constants.ActionNames.MAKE_RESOURCE_PRIVATE.value: response_msg = update_access_for_resource(auth_token, domain_id, datasource_id, action_payload, 'ALL', log_entry, action_key) elif action_key == action_constants.ActionNames.REMOVE_EXTERNAL_ACCESS_TO_RESOURCE.value: response_msg = update_access_for_resource( auth_token, domain_id, datasource_id, action_payload, constants.EntityExposureType.EXTERNAL.value, log_entry, action_key) # Single Resource permission change actions elif action_key == action_constants.ActionNames.UPDATE_PERMISSION_FOR_USER.value: response_msg = update_or_delete_resource_permission( auth_token, datasource_id, action_payload, log_entry) elif action_key == action_constants.ActionNames.DELETE_PERMISSION_FOR_USER.value: action_parameters['new_permission_role'] = '' response_msg = update_or_delete_resource_permission( auth_token, datasource_id, action_payload, log_entry) elif action_key == action_constants.ActionNames.ADD_PERMISSION_FOR_A_FILE.value: response_msg = add_resource_permission(auth_token, datasource_id, action_payload, log_entry) elif action_key == action_constants.ActionNames.CHANGE_OWNER_OF_FILE.value: action_parameters['new_permission_role'] = constants.Role.OWNER.value action_parameters['resource_owner_id'] = action_parameters[ "old_owner_email"] action_parameters['user_email'] = action_parameters["new_owner_email"] response_msg = update_or_delete_resource_permission( auth_token, datasource_id, action_payload, log_entry) # Uninstalling an app for a user elif action_key == action_constants.ActionNames.REMOVE_USER_FROM_APP.value: user_email = action_parameters['user_email'] app_id = action_parameters['app_id'] response_msg = revoke_user_app_access(auth_token, datasource_id, user_email, app_id, log_entry) # Uninstalling app for the entire domain elif action_key == action_constants.ActionNames.REMOVE_APP_FOR_DOMAIN.value: app_id = action_parameters["app_id"] response_msg = remove_app_for_domain(auth_token, app_id, log_entry) #Deleting a repository elif action_key == action_constants.ActionNames.DELETE_REPOSITORY.value: response_msg = delete_repository(auth_token, datasource_id, action_key, action_parameters, log_entry) elif action_key == action_constants.ActionNames.NOTIFY_MULTIPLE_USERS_FOR_CLEANUP.value: users_email = action_parameters['users_email'] users_name = action_parameters['users_name'] initiated_by = action_payload['initiated_by'] status_message = 'Action submitted successfully' log_entry.status = action_constants.ActionStatus.SUCCESS.value if len(users_email) > 0: for i, user_email in enumerate(users_email): modified_action_payload = dict(action_payload) modified_action_payload['parameters'] = { 'user_email': user_email, 'full_name': users_name[i] } modified_action_payload[ 'key'] = action_constants.ActionNames.NOTIFY_USER_FOR_CLEANUP.value modified_action_payload['log_id'] = log_entry.log_id messaging.trigger_post_event(urls.INITIATE_ACTION_PATH, auth_token, None, modified_action_payload) response_msg = ResponseMessage(200, status_message) elif action_key == action_constants.ActionNames.REMOVE_ALL_ACCESS_FOR_MULTIPLE_USERS.value: users_email = action_parameters['users_email'] initiated_by = action_payload['initiated_by'] status_message = 'Action submitted successfully' log_entry.status = action_constants.ActionStatus.SUCCESS.value response_msg = ResponseMessage(200, status_message) if len(users_email) > 0: for user_email in users_email: modified_action_payload = dict(action_payload) modified_action_payload['parameters'] = { 'user_email': user_email } modified_action_payload[ 'key'] = action_constants.ActionNames.REMOVE_ALL_ACCESS_FOR_USER.value modified_action_payload['log_id'] = log_entry.log_id messaging.trigger_post_event(urls.INITIATE_ACTION_PATH, auth_token, None, modified_action_payload) return response_msg
def update_or_delete_resource_permission(auth_token, datasource_id, action_payload, log_entry): action_parameters = action_payload['parameters'] new_permission_role = action_parameters['new_permission_role'] user_type = action_parameters[ 'user_type'] if 'user_type' in action_parameters else 'user' resource_id = action_parameters['resource_id'] resource_owner = action_parameters['resource_owner_id'] user_email = action_parameters['user_email'] initiated_user = action_payload['initiated_by'] current_time = datetime.utcnow() db_session = db_connection().get_session() existing_permission = db_session.query(ResourcePermission).filter( and_(ResourcePermission.resource_id == resource_id, ResourcePermission.datasource_id == datasource_id, ResourcePermission.email == user_email)).first() if not existing_permission and action_payload[ 'key'] == action_constants.ActionNames.CHANGE_OWNER_OF_FILE.value: Logger().info("add a new permission ") response = add_resource_permission(auth_token, datasource_id, action_payload, log_entry) return response if not existing_permission: status_message = "Bad Request - Permission not found in records" Logger().info(status_message) log_entry.status = action_constants.ActionStatus.FAILED.value log_entry.message = status_message return ResponseMessage(400, status_message) query_param = { 'user_email': resource_owner, 'initiated_by_email': initiated_user, 'datasource_id': datasource_id, "log_id": str(log_entry.log_id) } existing_permission_json = json.loads( json.dumps(existing_permission, cls=alchemy_encoder())) existing_permission_json["permission_type"] = new_permission_role body = json.dumps([existing_permission_json], cls=alchemy_encoder()) response = "Action executed" datasource_obj = get_datasource(datasource_id) datasource_type = datasource_obj.datasource_type payload = { "permissions": body, "datasource_id": datasource_id, "domain_id": datasource_obj.domain_id, "initiated_by_email": action_payload['initiated_by'], "log_id": str(log_entry.log_id), "user_email": resource_owner, "action_type": action_payload['key'], "resource_name": action_parameters["resource_name"] } response = messaging.trigger_post_event( datasource_execute_action_map[datasource_type], auth_token, None, payload, connector_servicename_map[datasource_type], constants.TriggerType.SYNC.value) if response and response.response_code == constants.SUCCESS_STATUS_CODE: return response_messages.ResponseMessage( constants.SUCCESS_STATUS_CODE, 'Action completed successfully') else: return response_messages.ResponseMessage( response.response_code, response.response_body['message'])