def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id) output_objects.append({'object_type': 'text', 'text' : '--------- Trying to Clean front end ----------' }) defaults = signature()[1] (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1] if not safe_handler(configuration, 'post', op_name, client_id, get_csrf_limit(configuration), accepted): output_objects.append( {'object_type': 'error_text', 'text': '''Only accepting CSRF-filtered POST requests to prevent unintended updates''' }) return (output_objects, returnvalues.CLIENT_ERROR) if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({'object_type': 'error_text', 'text' : 'Failure: You must be an owner of ' + unique_resource_name + ' to clean the front end!'}) return (output_objects, returnvalues.CLIENT_ERROR) exit_status = returnvalues.OK (status, msg) = stop_resource_frontend(unique_resource_name, configuration, logger) if not status: output_objects.append({'object_type': 'error_text', 'text' : 'Problems stopping front end during clean: %s' % msg}) return (output_objects, returnvalues.CLIENT_ERROR) (status2, msg2) = clean_resource_frontend(unique_resource_name, configuration.resource_home, logger) if not status2: output_objects.append({'object_type': 'error_text', 'text' : 'Problems cleaning front end during clean: %s' % msg2}) exit_status = returnvalues.SYSTEM_ERROR if status and status2: output_objects.append({'object_type': 'text', 'text' : 'Clean front end success: Stop output: %s Clean output %s' % (msg, msg2)}) return (output_objects, exit_status)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id) defaults = signature()[1] (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1] if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({ 'object_type': 'error_text', 'text': 'You must be an owner of %s to get the list of owners!' % unique_resource_name }) return (output_objects, returnvalues.CLIENT_ERROR) # is_owner incorporates unique_resource_name verification - no need to # specifically check for illegal directory traversal base_dir = os.path.abspath( os.path.join(configuration.resource_home, unique_resource_name)) + os.sep owners_file = os.path.join(base_dir, 'owners') (list_status, msg) = list_items_in_pickled_list(owners_file, logger) if not list_status: output_objects.append({ 'object_type': 'error_text', 'text': 'Could not get list of owners, reason: %s' % msg }) return (output_objects, returnvalues.SYSTEM_ERROR) output_objects.append({'object_type': 'list', 'list': msg}) return (output_objects, returnvalues.OK)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id, op_header=False) defaults = signature()[1] output_objects.append({ 'object_type': 'header', 'text': 'Remove Resource Owner' }) (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1] cert_id = accepted['cert_id'][-1] if not safe_handler(configuration, 'post', op_name, client_id, get_csrf_limit(configuration), accepted): output_objects.append({ 'object_type': 'error_text', 'text': '''Only accepting CSRF-filtered POST requests to prevent unintended updates''' }) return (output_objects, returnvalues.CLIENT_ERROR) if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({ 'object_type': 'error_text', 'text': 'You must be an owner of %s to remove another owner!' % unique_resource_name }) return (output_objects, returnvalues.CLIENT_ERROR) # is_owner incorporates unique_resource_name verification - no need to # specifically check for illegal directory traversal if not is_user(cert_id, configuration.mig_server_home): output_objects.append({'object_type': 'error_text', 'text' : '%s is not a valid %s user!' % \ (cert_id, configuration.short_title) }) return (output_objects, returnvalues.CLIENT_ERROR) # reject remove if cert_id is not an owner if not resource_is_owner(unique_resource_name, cert_id, configuration): output_objects.append({ 'object_type': 'error_text', 'text': '%s is not an owner of %s.' % (cert_id, unique_resource_name) }) return (output_objects, returnvalues.CLIENT_ERROR) # Remove owner (rm_status, rm_msg) = resource_remove_owners(configuration, unique_resource_name, [cert_id]) if not rm_status: output_objects.append({ 'object_type': 'error_text', 'text': 'Could not remove owner, reason: %s' % rm_msg }) return (output_objects, returnvalues.SYSTEM_ERROR) output_objects.append({ 'object_type': 'text', 'text': '%s was successfully removed and is no longer an owner of %s!' % (cert_id, unique_resource_name) }) output_objects.append({'object_type': 'link', 'destination': 'resadmin.py?unique_resource_name=%s' % \ unique_resource_name, 'class': 'adminlink iconspace', 'title': 'Administrate resource', 'text': 'Manage resource'}) return (output_objects, returnvalues.OK)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id) output_objects.append({ 'object_type': 'text', 'text': '--------- Trying to RESTART exe ----------' }) defaults = signature()[1] (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1] cputime = accepted['cputime'][-1] exe_name_list = accepted['exe_name'] all = accepted['all'][-1].lower() == 'true' parallel = accepted['parallel'][-1].lower() == 'true' if not configuration.site_enable_resources: output_objects.append({ 'object_type': 'error_text', 'text': '''Resources are not enabled on this system''' }) return (output_objects, returnvalues.SYSTEM_ERROR) if not safe_handler(configuration, 'post', op_name, client_id, get_csrf_limit(configuration), accepted): output_objects.append({ 'object_type': 'error_text', 'text': '''Only accepting CSRF-filtered POST requests to prevent unintended updates''' }) return (output_objects, returnvalues.CLIENT_ERROR) if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({ 'object_type': 'error_text', 'text': 'Failure: You must be an owner of ' + unique_resource_name + ' to restart the exe!' }) return (output_objects, returnvalues.CLIENT_ERROR) exit_status = returnvalues.OK if all: exe_name_list = get_all_exe_names(unique_resource_name) # take action based on supplied list of exes if len(exe_name_list) == 0: output_objects.append({ 'object_type': 'text', 'text': "No exes specified and 'all' argument not set to true: Nothing to do!" }) workers = [] task_list = [] for exe_name in exe_name_list: task = Worker(target=stop_resource_exe, args=(unique_resource_name, exe_name, configuration.resource_home, logger)) workers.append((exe_name, [task])) task_list.append(task) throttle_max_concurrent(task_list) task.start() if not parallel: task.join() # Complete each stop thread before launching corresponding start threads for (exe_name, task_list) in workers: # We could optimize with non-blocking join here but keep it simple for now # as final result will need to wait for slowest member anyway task_list[0].join() task = Worker(target=start_resource_exe, args=(unique_resource_name, exe_name, configuration.resource_home, int(cputime), logger)) task_list.append(task) throttle_max_concurrent(task_list) task.start() if not parallel: task.join() for (exe_name, task_list) in workers: (status, msg) = task_list[0].finish() output_objects.append({ 'object_type': 'header', 'text': 'Restart exe output:' }) if not status: output_objects.append({ 'object_type': 'error_text', 'text': 'Problems stopping exe during restart: %s' % msg }) (status2, msg2) = task_list[1].finish() if not status2: output_objects.append({ 'object_type': 'error_text', 'text': 'Problems starting exe during restart: %s' % msg2 }) exit_status = returnvalues.SYSTEM_ERROR if status and status2: output_objects.append({ 'object_type': 'text', 'text': 'Restart exe success: Stop output: %s ; Start output: %s' % (msg, msg2) }) return (output_objects, exit_status)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id, op_header=False, op_title=False, op_menu=client_id) defaults = signature()[1] (validate_status, accepted) = validate_input(user_arguments_dict, defaults, output_objects, allow_rejects=False) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) remote_ip = str(os.getenv('REMOTE_ADDR')) res_type = accepted['type'][-1] unique_resource_name = accepted['unique_resource_name'][-1] exe_name = accepted['exe_name'][-1] status = returnvalues.OK if not configuration.site_enable_resources: output_objects.append({ 'object_type': 'error_text', 'text': "Resources are not enabled on this site" }) return (output_objects, returnvalues.CLIENT_ERROR) # Web format for cert access and no header for SID access if client_id: output_objects.append({ 'object_type': 'title', 'text': 'Load resource script PGID' }) output_objects.append({ 'object_type': 'header', 'text': 'Load resource script PGID' }) else: output_objects.append({'object_type': 'start'}) # Please note that base_dir must end in slash to avoid access to other # resource dirs when own name is a prefix of another resource name base_dir = os.path.abspath( os.path.join(configuration.resource_home, unique_resource_name)) + os.sep if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({ 'object_type': 'error_text', 'text': "Failure: You must be an owner of '%s' to get the PGID!" % unique_resource_name }) return (output_objects, returnvalues.CLIENT_ERROR) # is_owner incorporates unique_resource_name verification - no need to # specifically check for illegal directory traversal on that variable. # exe_name is not automatically checked however - do it manually if not valid_dir_input(base_dir, 'EXE_' + exe_name + '.PGID'): # out of bounds - rogue resource!?!? output_objects.append({ 'object_type': 'error_text', 'text': 'invalid exe_name! %s' % exe_name }) logger.error('''getrespgid called with illegal parameter(s) in what appears to be an illegal directory traversal attempt!: unique_resource_name %s, exe %s, client_id %s''' % (unique_resource_name, exe_name, client_id)) return (output_objects, returnvalues.CLIENT_ERROR) # Check that resource address matches request source to make DoS harder try: check_source_ip(remote_ip, unique_resource_name) except ValueError as vae: output_objects.append({ 'object_type': 'error_text', 'text': 'invalid request: %s' % vae }) logger.error("Invalid put pgid: %s" % vae) return (output_objects, returnvalues.CLIENT_ERROR) # TODO: add full session ID check here if 'FE' == res_type: pgid_path = os.path.join(base_dir, 'FE.PGID') elif 'EXE' == res_type: pgid_path = os.path.join(base_dir + 'EXE_%s.PGID' % exe_name) else: output_objects.append({ 'object_type': 'error_text', 'text': "Unknown type: '%s'" % res_type }) return (output_objects, returnvalues.CLIENT_ERROR) try: pgid_file = open(pgid_path, 'r+') fcntl.flock(pgid_file, fcntl.LOCK_EX) pgid_file.seek(0, 0) pgid = pgid_file.readline().strip() fcntl.flock(pgid_file, fcntl.LOCK_UN) pgid_file.close() msg = "%s\n'%s' PGID succesfully retrieved." % (pgid, res_type) except Exception as err: if 'FE' == res_type: msg = "Resource frontend: '%s' is stopped." % unique_resource_name elif 'EXE' == res_type: msg = ("Error reading PGID for resource: '%s' EXE: '%s'\n" 'Either resource has never been started or a server ' 'error occured.') % (unique_resource_name, exe_name) status = returnvalues.CLIENT_ERROR # Status code line followed by raw output if not client_id: output_objects.append({'object_type': 'script_status', 'text': ''}) output_objects.append({ 'object_type': 'binary', 'data': '%s' % status[0] }) output_objects.append({'object_type': 'binary', 'data': msg}) return (output_objects, status)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id, op_header=False) defaults = signature()[1] status = returnvalues.OK output_objects.append({ 'object_type': 'header', 'text': 'Add Resource Owner(s)' }) (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1].strip() cert_id_list = accepted['cert_id'] request_name = unhexlify(accepted['request_name'][-1]) if not safe_handler(configuration, 'post', op_name, client_id, get_csrf_limit(configuration), accepted): output_objects.append({ 'object_type': 'error_text', 'text': '''Only accepting CSRF-filtered POST requests to prevent unintended updates''' }) return (output_objects, returnvalues.CLIENT_ERROR) if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({ 'object_type': 'error_text', 'text': 'You must be an owner of %s to add a new owner!' % unique_resource_name }) return (output_objects, returnvalues.CLIENT_ERROR) # is_owner incorporates unique_resource_name verification - no need to # specifically check for illegal directory traversal cert_id_added = [] for cert_id in cert_id_list: cert_id = cert_id.strip() if not cert_id: continue if not is_user(cert_id, configuration.mig_server_home): output_objects.append({ 'object_type': 'error_text', 'text': '%s is not a valid %s user!' % (cert_id, configuration.short_title) }) status = returnvalues.CLIENT_ERROR continue # don't add if already an owner if resource_is_owner(unique_resource_name, cert_id, configuration): output_objects.append({ 'object_type': 'error_text', 'text': '%s is already an owner of %s.' % (cert_id, unique_resource_name) }) status = returnvalues.CLIENT_ERROR continue # Add owner (add_status, add_msg) = resource_add_owners(configuration, unique_resource_name, [cert_id]) if not add_status: output_objects.append({ 'object_type': 'error_text', 'text': 'Could not add new owner, reason: %s' % add_msg }) status = returnvalues.SYSTEM_ERROR continue cert_id_added.append(cert_id) if request_name: request_dir = os.path.join(configuration.resource_home, unique_resource_name) if not delete_access_request(configuration, request_dir, request_name): logger.error("failed to delete owner request for %s in %s" % \ (unique_resource_name, request_name)) output_objects.append({ 'object_type': 'error_text', 'text': 'Failed to remove saved request for %s in %s!' % \ (unique_resource_name, request_name)}) if cert_id_added: output_objects.append({ 'object_type': 'html_form', 'text': 'New owner(s)<br/>%s<br/>successfully added to %s!' % ('<br />'.join(cert_id_added), unique_resource_name) }) cert_id_fields = '' for cert_id in cert_id_added: cert_id_fields += """<input type=hidden name=cert_id value='%s' /> """ % cert_id form_method = 'post' csrf_limit = get_csrf_limit(configuration) fill_helpers = { 'res_id': unique_resource_name, 'cert_id_fields': cert_id_fields, 'any_protocol': any_protocol, 'form_method': form_method, 'csrf_field': csrf_field, 'csrf_limit': csrf_limit } target_op = 'sendrequestaction' csrf_token = make_csrf_token(configuration, form_method, target_op, client_id, csrf_limit) fill_helpers.update({'target_op': target_op, 'csrf_token': csrf_token}) output_objects.append({ 'object_type': 'html_form', 'text': """ <form method='%(form_method)s' action='%(target_op)s.py'> <input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' /> <input type=hidden name=request_type value='resourceaccept' /> <input type=hidden name=unique_resource_name value='%(res_id)s' /> %(cert_id_fields)s <input type=hidden name=protocol value='%(any_protocol)s' /> <table> <tr> <td class='title'>Custom message to user(s)</td> </tr> <tr> <td><textarea name=request_text cols=72 rows=10> We have granted you ownership access to our %(res_id)s resource. You can access the resource administration page from the Resources page. Regards, the %(res_id)s resource owners </textarea></td> </tr> <tr> <td><input type='submit' value='Inform user(s)' /></td> </tr> </table> </form> <br /> """ % fill_helpers }) output_objects.append({'object_type': 'link', 'destination': 'resadmin.py?unique_resource_name=%s' % \ unique_resource_name, 'class': 'adminlink iconspace', 'title': 'Administrate resource', 'text': 'Manage resource'}) return (output_objects, status)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id, op_header=False) defaults = signature()[1] output_objects.append({ 'object_type': 'header', 'text': 'Reject Resource Request' }) (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1].strip() request_name = unhexlify(accepted['request_name'][-1]) if not safe_handler(configuration, 'post', op_name, client_id, get_csrf_limit(configuration), accepted): output_objects.append({ 'object_type': 'error_text', 'text': '''Only accepting CSRF-filtered POST requests to prevent unintended updates''' }) return (output_objects, returnvalues.CLIENT_ERROR) if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({ 'object_type': 'error_text', 'text': 'You must be an owner of %s to reject requests!' % unique_resource_name }) return (output_objects, returnvalues.CLIENT_ERROR) # Please note that base_dir must end in slash to avoid access to other # resource dirs when own name is a prefix of another user name base_dir = \ os.path.abspath(os.path.join(configuration.resource_home, unique_resource_name)) + os.sep # IMPORTANT: path must be expanded to abs for proper chrooting abs_path = os.path.abspath(os.path.join(base_dir, request_name)) if not valid_user_path( configuration, abs_path, base_dir, allow_equal=False): logger.warning('%s tried to access restricted path %s ! (%s)' % \ (client_id, abs_path, request_name)) output_objects.append({ 'object_type': 'error_text', 'text': '''Illegal request name "%s": you can only reject requests to your own resources.''' % request_name }) return (output_objects, returnvalues.CLIENT_ERROR) if request_name: request_dir = os.path.join(configuration.resource_home, unique_resource_name) req = load_access_request(configuration, request_dir, request_name) if not req or not delete_access_request(configuration, request_dir, request_name): logger.error("failed to delete owner request for %s in %s" % \ (unique_resource_name, request_name)) output_objects.append({ 'object_type': 'error_text', 'text': 'Failed to remove saved resource request for %s in %s!'\ % (unique_resource_name, request_name)}) return (output_objects, returnvalues.CLIENT_ERROR) output_objects.append({ 'object_type': 'text', 'text': ''' Deleted %(request_type)s access request to %(target)s for %(entity)s . ''' % req }) form_method = 'post' csrf_limit = get_csrf_limit(configuration) fill_helpers = { 'protocol': any_protocol, 'unique_resource_name': unique_resource_name, 'form_method': form_method, 'csrf_field': csrf_field, 'csrf_limit': csrf_limit } fill_helpers.update(req) target_op = 'sendrequestaction' csrf_token = make_csrf_token(configuration, form_method, target_op, client_id, csrf_limit) fill_helpers.update({'target_op': target_op, 'csrf_token': csrf_token}) output_objects.append({ 'object_type': 'html_form', 'text': """ <p> You can use the reply form below if you want to additionally send an explanation for rejecting the request. </p> <form method='%(form_method)s' action='%(target_op)s.py'> <input type='hidden' name='%(csrf_field)s' value='%(csrf_token)s' /> <input type=hidden name=request_type value='resourcereject' /> <input type=hidden name=unique_resource_name value='%(target)s' /> <input type=hidden name=cert_id value='%(entity)s' /> <input type=hidden name=protocol value='%(protocol)s' /> <table> <tr> <td class='title'>Optional reject message to requestor(s)</td> </tr><tr> <td><textarea name=request_text cols=72 rows=10> We have decided to reject your %(request_type)s request to our %(target)s resource. Regards, the %(target)s resource owners </textarea></td> </tr> <tr> <td><input type='submit' value='Inform requestor(s)' /></td> </tr> </table> </form> <br /> """ % fill_helpers }) output_objects.append({ 'object_type': 'link', 'destination': 'resadmin.py?unique_resource_name=%s' % unique_resource_name, 'text': 'Back to administration for %s' % unique_resource_name }) return (output_objects, returnvalues.OK)
def main(client_id, user_arguments_dict): """Main function used by front end""" (configuration, logger, output_objects, op_name) = \ initialize_main_variables(client_id) output_objects.append({'object_type': 'text', 'text': '--------- Trying to RESTART frontend ----------' }) defaults = signature()[1] (validate_status, accepted) = validate_input_and_cert( user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, ) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) unique_resource_name = accepted['unique_resource_name'][-1] if not configuration.site_enable_resources: output_objects.append({'object_type': 'error_text', 'text': '''Resources are not enabled on this system'''}) return (output_objects, returnvalues.SYSTEM_ERROR) if not safe_handler(configuration, 'post', op_name, client_id, get_csrf_limit(configuration), accepted): output_objects.append( {'object_type': 'error_text', 'text': '''Only accepting CSRF-filtered POST requests to prevent unintended updates''' }) return (output_objects, returnvalues.CLIENT_ERROR) logger.info('%s attempts to restart frontend at %s', client_id, unique_resource_name) if not is_owner(client_id, unique_resource_name, configuration.resource_home, logger): output_objects.append({'object_type': 'error_text', 'text': 'You must be an owner of ' + unique_resource_name + ' to restart the resource frontend!'}) return (output_objects, returnvalues.CLIENT_ERROR) (status, msg) = stop_resource(unique_resource_name, configuration.resource_home, logger) if not status: output_objects.append( {'object_type': 'error_text', 'text': '%s. Error stopping resource' % msg}) return (output_objects, returnvalues.CLIENT_ERROR) (status, msg2) = start_resource(unique_resource_name, configuration.resource_home, configuration.migserver_https_sid_url, logger) if not status: output_objects.append( {'object_type': 'error_text', 'text': '%s. Error starting resource' % msg}) return (output_objects, returnvalues.CLIENT_ERROR) # everything ok output_objects.append({'object_type': 'text', 'text': 'Stop output: %s ; Start output: %s' % (msg, msg2)}) return (output_objects, returnvalues.OK)