def dump(obj, path, protocol=0): """Dump a binary representation of obj to the file, path""" contents = dumps(obj) fd = distfile.DistFile(path, 'w') fd.lock(LOCK_EX) fd.write(contents) fd.flush() fd.unlock() fd.close()
def save_access_request(configuration, request_dir, request): """Save the request dictionary as a pickle in request_dir with random filename stem and predefined request file extension. Returns the nameof the file on success. """ request['created_timestamp'] = datetime.datetime.now() try: (filehandle, tmpfile) = make_temp_file(suffix=request_ext, prefix=request_prefix, dir=request_dir) # Prevent exotic characters causing trouble between scripts request['request_name'] = os.path.basename(tmpfile) os.write(filehandle, dumps(request)) os.close(filehandle) except Exception as err: configuration.logger.error("could not save request %s in %s: %s" % \ (request, request_dir, err)) return False return os.path.basename(tmpfile)
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_menu=False) defaults = signature()[1] logger.debug('in extoidaction: %s' % user_arguments_dict) (validate_status, accepted) = validate_input(user_arguments_dict, defaults, output_objects, allow_rejects=False) if not validate_status: return (accepted, returnvalues.CLIENT_ERROR) # Unfortunately OpenID does not use POST # 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) title_entry = find_entry(output_objects, 'title') title_entry[ 'text'] = '%s OpenID account sign up' % configuration.short_title title_entry['skipmenu'] = True output_objects.append({ 'object_type': 'header', 'text': '%s OpenID account sign up' % configuration.short_title }) admin_email = configuration.admin_email smtp_server = configuration.smtp_server user_pending = os.path.abspath(configuration.user_pending) # force name to capitalized form (henrik karlsen -> Henrik Karlsen) id_url = os.environ['REMOTE_USER'].strip() openid_prefix = configuration.user_ext_oid_provider.rstrip('/') + '/' raw_login = id_url.replace(openid_prefix, '') full_name = accepted['openid.sreg.full_name'][-1].strip().title() country = accepted['openid.sreg.country'][-1].strip().upper() state = accepted['state'][-1].strip().title() organization = accepted['openid.sreg.organization'][-1].strip() organizational_unit = accepted['openid.sreg.organizational_unit'][ -1].strip() locality = accepted['openid.sreg.locality'][-1].strip() # lower case email address email = accepted['openid.sreg.email'][-1].strip().lower() password = accepted['password'][-1] #verifypassword = accepted['verifypassword'][-1] # keep comment to a single line comment = accepted['comment'][-1].replace('\n', ' ') # single quotes break command line format - remove comment = comment.replace("'", ' ') accept_terms = (accepted['accept_terms'][-1].strip().lower() in ('1', 'o', 'y', 't', 'on', 'yes', 'true')) 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 accept_terms: output_objects.append({ 'object_type': 'error_text', 'text': 'You must accept the terms of use in sign up!' }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) user_dict = { 'full_name': full_name, 'organization': organization, 'organizational_unit': organizational_unit, 'locality': locality, 'state': state, 'country': country, 'email': email, 'password': password, 'comment': comment, 'expire': default_account_expire(configuration, 'oid'), 'openid_names': [raw_login], 'auth': ['extoid'], } fill_distinguished_name(user_dict) user_id = user_dict['distinguished_name'] if configuration.user_openid_providers and configuration.user_openid_alias: user_dict['openid_names'].append( user_dict[configuration.user_openid_alias]) req_path = None try: (os_fd, req_path) = tempfile.mkstemp(dir=user_pending) os.write(os_fd, dumps(user_dict)) os.close(os_fd) except Exception as err: logger.error('Failed to write OpenID account request to %s: %s' % (req_path, err)) output_objects.append({ 'object_type': 'error_text', 'text': '''Request could not be sent to site administrators. Please contact them manually on %s if this error persists.''' % admin_email }) return (output_objects, returnvalues.SYSTEM_ERROR) logger.info('Wrote OpenID account request to %s' % req_path) tmp_id = req_path.replace(user_pending, '') user_dict['tmp_id'] = tmp_id # TODO: remove cert generation or generate pw for it mig_user = os.environ.get('USER', 'mig') helper_commands = user_manage_commands(configuration, mig_user, req_path, user_id, user_dict, 'oid') user_dict.update(helper_commands) user_dict['site'] = configuration.short_title user_dict['vgrid_label'] = configuration.site_vgrid_label user_dict['vgridman_links'] = generate_https_urls( configuration, '%(auto_base)s/%(auto_bin)s/vgridman.py', {}) email_header = '%s OpenID request for %s' % \ (configuration.short_title, full_name) email_msg = """ Received an OpenID account sign up with user data * Full Name: %(full_name)s * Organization: %(organization)s * State: %(state)s * Country: %(country)s * Email: %(email)s * Comment: %(comment)s * Expire: %(expire)s Command to create user on %(site)s server: %(command_user_create)s Optional command to create matching certificate: %(command_cert_create)s Finally add the user %(distinguished_name)s to any relevant %(vgrid_label)ss using one of the management links: %(vgridman_links)s --- If user must be denied access or deleted at some point --- Command to reject user account request on %(site)s server: %(command_user_reject)s Remove the user %(distinguished_name)s from any relevant %(vgrid_label)ss using one of the management links: %(vgridman_links)s Optional command to revoke any user certificates: %(command_cert_revoke)s You need to copy the resulting signed certificate revocation list (crl.pem) to the web server(s) for the revocation to take effect. Command to suspend user on %(site)s server: %(command_user_suspend)s Command to delete user again on %(site)s server: %(command_user_delete)s --- """ % user_dict logger.info('Sending email: to: %s, header: %s, msg: %s, smtp_server: %s' % (admin_email, email_header, email_msg, smtp_server)) if not send_email(admin_email, email_header, email_msg, logger, configuration): output_objects.append({ 'object_type': 'error_text', 'text': '''An error occured trying to send the email requesting your new user account. Please email the site administrators (%s) manually and include the session ID: %s''' % (admin_email, tmp_id) }) return (output_objects, returnvalues.SYSTEM_ERROR) output_objects.append({ 'object_type': 'text', 'text': """Request sent to site administrators: Your user account will be created as soon as possible, so please be patient. Once handled an email will be sent to the account you have specified ('%s') with further information. In case of inquiries about this request, please email the site administrators (%s) and include the session ID: %s""" % (email, configuration.admin_email, tmp_id) }) 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, op_menu=False) defaults = signature()[1] (validate_status, accepted) = validate_input(user_arguments_dict, defaults, output_objects, allow_rejects=False) if not validate_status: logger.warning('%s invalid input: %s' % (op_name, accepted)) return (accepted, returnvalues.CLIENT_ERROR) if not configuration.site_enable_openid or \ not 'migoid' in configuration.site_signup_methods: output_objects.append({ 'object_type': 'error_text', 'text': '''Local OpenID login is not enabled on this site''' }) return (output_objects, returnvalues.SYSTEM_ERROR) title_entry = find_entry(output_objects, 'title') title_entry['text'] = '%s OpenID account request' % \ configuration.short_title title_entry['skipmenu'] = True output_objects.append({ 'object_type': 'header', 'text': '%s OpenID account request' % configuration.short_title }) admin_email = configuration.admin_email smtp_server = configuration.smtp_server user_pending = os.path.abspath(configuration.user_pending) # TODO: switch to canonical_user fra mig.shared.base instead? # force name to capitalized form (henrik karlsen -> Henrik Karlsen) # please note that we get utf8 coded bytes here and title() treats such # chars as word termination. Temporarily force to unicode. raw_name = accepted['cert_name'][-1].strip() try: cert_name = force_utf8(force_unicode(raw_name).title()) except Exception: cert_name = raw_name.title() country = accepted['country'][-1].strip().upper() state = accepted['state'][-1].strip().upper() org = accepted['org'][-1].strip() # lower case email address email = accepted['email'][-1].strip().lower() password = accepted['password'][-1] verifypassword = accepted['verifypassword'][-1] # The checkbox typically returns value 'on' if selected passwordrecovery = (accepted['passwordrecovery'][-1].strip().lower() in ('1', 'o', 'y', 't', 'on', 'yes', 'true')) # keep comment to a single line comment = accepted['comment'][-1].replace('\n', ' ') # single quotes break command line format - remove comment = comment.replace("'", ' ') accept_terms = (accepted['accept_terms'][-1].strip().lower() in ('1', 'o', 'y', 't', 'on', 'yes', 'true')) 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 accept_terms: output_objects.append({ 'object_type': 'error_text', 'text': 'You must accept the terms of use in sign up!' }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) if password != verifypassword: output_objects.append({ 'object_type': 'error_text', 'text': 'Password and verify password are not identical!' }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) try: assure_password_strength(configuration, password) except Exception as exc: logger.warning( "%s invalid password for '%s' (policy %s): %s" % (op_name, cert_name, configuration.site_password_policy, exc)) output_objects.append({ 'object_type': 'error_text', 'text': 'Invalid password requested: %s.' % exc }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) if not existing_country_code(country, configuration): output_objects.append({ 'object_type': 'error_text', 'text': '''Illegal country code: Please read and follow the instructions shown in the help bubble when filling the country field on the request page! Specifically if you are from the U.K. you need to use GB as country code in line with the ISO-3166 standard. ''' }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) # TODO: move this check to conf? if not forced_org_email_match(org, email, configuration): output_objects.append({ 'object_type': 'error_text', 'text': '''Illegal email and organization combination: Please read and follow the instructions in red on the request page! If you are a student with only a @*.ku.dk address please just use KU as organization. As long as you state that you want the account for course purposes in the comment field, you will be given access to the necessary resources anyway. ''' }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) # NOTE: we save password on scrambled form only if explicitly requested if passwordrecovery: logger.info('saving %s scrambled password to enable recovery' % email) scrambled_pw = scramble_password(configuration.site_password_salt, password) else: logger.info('only saving %s password hash' % email) scrambled_pw = '' user_dict = { 'full_name': cert_name, 'organization': org, 'state': state, 'country': country, 'email': email, 'comment': comment, 'password': scrambled_pw, 'password_hash': make_hash(password), 'expire': default_account_expire(configuration, 'oid'), 'openid_names': [], 'auth': ['migoid'], } fill_distinguished_name(user_dict) user_id = user_dict['distinguished_name'] user_dict['authorized'] = (user_id == client_id) if configuration.user_openid_providers and configuration.user_openid_alias: user_dict['openid_names'] += \ [user_dict[configuration.user_openid_alias]] logger.info('got account request from reqoid: %s' % user_dict) # For testing only if cert_name.upper().find('DO NOT SEND') != -1: output_objects.append({ 'object_type': 'text', 'text': "Test request ignored!" }) return (output_objects, returnvalues.OK) req_path = None try: (os_fd, req_path) = tempfile.mkstemp(dir=user_pending) os.write(os_fd, dumps(user_dict)) os.close(os_fd) except Exception as err: logger.error('Failed to write OpenID account request to %s: %s' % (req_path, err)) output_objects.append({ 'object_type': 'error_text', 'text': '''Request could not be sent to site administrators. Please contact them manually on %s if this error persists.''' % admin_email }) return (output_objects, returnvalues.SYSTEM_ERROR) logger.info('Wrote OpenID account request to %s' % req_path) tmp_id = os.path.basename(req_path) user_dict['tmp_id'] = tmp_id mig_user = os.environ.get('USER', 'mig') helper_commands = user_manage_commands(configuration, mig_user, req_path, user_id, user_dict, 'oid') user_dict.update(helper_commands) user_dict['site'] = configuration.short_title user_dict['vgrid_label'] = configuration.site_vgrid_label user_dict['vgridman_links'] = generate_https_urls( configuration, '%(auto_base)s/%(auto_bin)s/vgridman.py', {}) email_header = '%s OpenID request for %s' % \ (configuration.short_title, cert_name) email_msg = \ """ Received an OpenID request with account data * Full Name: %(full_name)s * Organization: %(organization)s * State: %(state)s * Country: %(country)s * Email: %(email)s * Comment: %(comment)s * Expire: %(expire)s Command to create user on %(site)s server: %(command_user_create)s Command to inform user and %(site)s admins: %(command_user_notify)s Optional command to create matching certificate: %(command_cert_create)s Finally add the user %(distinguished_name)s to any relevant %(vgrid_label)ss using one of the management links: %(vgridman_links)s --- If user must be denied access or deleted at some point --- Command to reject user account request on %(site)s server: %(command_user_reject)s Remove the user %(distinguished_name)s from any relevant %(vgrid_label)ss using one of the management links: %(vgridman_links)s Optional command to revoke any matching user certificate: %(command_cert_revoke)s You need to copy the resulting signed certificate revocation list (crl.pem) to the web server(s) for the revocation to take effect. Command to suspend user on %(site)s server: %(command_user_suspend)s Command to delete user again on %(site)s server: %(command_user_delete)s --- """ % user_dict logger.info('Sending email: to: %s, header: %s, msg: %s, smtp_server: %s' % (admin_email, email_header, email_msg, smtp_server)) if not send_email(admin_email, email_header, email_msg, logger, configuration): output_objects.append({ 'object_type': 'error_text', 'text': '''An error occured trying to send the email requesting the site administrators to create a new OpenID and account. Please email them (%s) manually and include the session ID: %s''' % (admin_email, tmp_id) }) return (output_objects, returnvalues.SYSTEM_ERROR) output_objects.append({ 'object_type': 'text', 'text': """Request sent to site administrators: Your OpenID account request will be verified and handled as soon as possible, so please be patient. Once handled an email will be sent to the account you have specified ('%s') with further information. In case of inquiries about this request, please email the site administrators (%s) and include the session ID: %s""" % (email, configuration.admin_email, tmp_id) }) return (output_objects, returnvalues.OK)
def run(configuration, localfile_spaces, unique_resource_name, outfile='AUTOMATIC'): """Parse configuration in localfile_spaces and write results to outfile if non-empty. The keyword AUTOMATIC is replaced by the expected resource configuration path. """ if not configuration: configuration = get_configuration_object() (status, msg, conf) = get_resource_config_dict(configuration, localfile_spaces) if not status: return (False, msg) # verify runtime environments are specified correctly if 'RUNTIMEENVIRONMENT' in conf: for re in conf['RUNTIMEENVIRONMENT']: try: (name, value) = re except Exception as err: return (False, 'Runtime environment error: %s' % err) if not is_runtime_environment(name, configuration): return ( False, "Non existing runtime environment specified ('%s'), please create the runtime environment before specifying it in resource configurations." % name) (re_dict, msg) = get_re_dict(name, configuration) if not re_dict: return (False, 'Runtime environment error, could not open (%s) %s' % (name, msg)) if 'ENVIRONMENTVARIABLE' not in re_dict: if value: # res conf has envs, but according to the template it should not return ( False, "%s should not have any environments and you specified '%s'. Details about the runtime environment <a href=showre.py?re_name=%s>here</a>" % (re, value, name)) else: continue re_dict_environments = re_dict['ENVIRONMENTVARIABLE'] re_dict_environment_names = [] for re_environment in re_dict_environments: re_dict_environment_names.append(re_environment['name']) if not len(value) == len(re_dict_environments): return ( False, "You have specified %s environments, but the runtime environment '%s' requires %s. Details about the runtime environment <a href='showre.py?re_name=%s'>here.</a>" % (len(value), name, len(re_dict_environments), name)) # we now know that the number of environments are # correct, verify that there are no name duplicates used_envnames = [] for env in value: try: (envname, _) = env if envname in used_envnames: # same envname used twice return ( False, "You have specified the environment '%s' more than once for the '%s' runtime environment." % (envname, name)) used_envnames.append(envname) except Exception as err: return ( False, 'Runtimeenvironment error: Name and value not found in env: %s' % err) # verify environment names are correct according to the # runtime environment definition do this by comparing # list of names specified for runtime environment and # res. conf. # re_dict_environment_names and used_envnames should # have the same entries! for n in re_dict_environment_names: # any build-in list comparison functionality? if not n in used_envnames: return ( False, "You have not specified an environment named '%s' which is required by the '%s' runtime environment. Details about the runtime environment <a href=showre.py?re_name=%s>here.</a>" % (n, name, name)) # check VGrid access vgrid_label = configuration.site_vgrid_label for (unit_config, unit_name) in (('EXECONFIG', '+EXENAME+'), ('STORECONFIG', '+STORENAME+')): for res_unit in conf[unit_config]: # replace unit_name with specified res_unit name for res_unit_key in res_unit.keys(): if type(res_unit[res_unit_key]) == type(''): res_unit[res_unit_key] = res_unit[res_unit_key].replace( unit_name, res_unit['name']) # verify resource is in specified vgrid vgrid_name = res_unit['vgrid'] # print "vgrid_name in res_unit" + vgrid_name if vgrid_name == '': # ok pass else: if type(vgrid_name) == type([]): # list for vgrid in vgrid_name: if not vgrid_is_default(vgrid) and not \ vgrid_is_resource(vgrid, unique_resource_name, configuration): return (False, """Your resource is not allowed in the %s '%s' specified in the configuation for the '%s' resource unit. Please contact the %s owner and ask if you can be included in the %s.""" % (vgrid_label, vgrid, res_unit['name'], vgrid_label, vgrid_label)) else: # string if not vgrid_is_default(vgrid) and not vgrid_is_resource( vgrid_name, unique_resource_name, configuration): return (False, """Your resource is not allowed in the %s '%s' specified in the configuation for the '%s' resource unit. Please contact the %s owner and ask if you can be included in the %s.""" % (vgrid_label, vgrid_name, res_unit['name'], vgrid_label, vgrid_label)) # save dictionary to a file if outfile == 'AUTOMATIC': # save configuration as python dictionary in the resource' private directory filename = configuration.resource_home + unique_resource_name\ + '/config' elif outfile: # outfile specified (DumpConfig) filename = outfile else: return (True, 'Everything ok') try: fsock = open(filename, 'w') st = dumps(conf, 0) fsock.write(st) fsock.close() except Exception as err: return (False, "Fatal error: could not open '" + filename + "' for writing!" + '\n Msg: ' + str(err)) return (True, 'Everything ok, config updated')
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) output_objects.append({ 'object_type': 'header', 'text': '%s external certificate sign up' % configuration.short_title }) defaults = signature()[1] (validate_status, accepted) = validate_input_and_cert(user_arguments_dict, defaults, output_objects, client_id, configuration, allow_rejects=False, require_user=False) if not validate_status: logger.warning('%s invalid input: %s' % (op_name, accepted)) return (accepted, returnvalues.CLIENT_ERROR) admin_email = configuration.admin_email smtp_server = configuration.smtp_server user_pending = os.path.abspath(configuration.user_pending) cert_id = accepted['cert_id'][-1].strip() # TODO: switch to canonical_user fra mig.shared.base instead? # force name to capitalized form (henrik karlsen -> Henrik Karlsen) # please note that we get utf8 coded bytes here and title() treats such # chars as word termination. Temporarily force to unicode. raw_name = accepted['cert_name'][-1].strip() try: cert_name = force_utf8(force_unicode(raw_name).title()) except Exception: cert_name = raw_name.title() country = accepted['country'][-1].strip().upper() state = accepted['state'][-1].strip().upper() org = accepted['org'][-1].strip() # lower case email address email = accepted['email'][-1].strip().lower() # keep comment to a single line comment = accepted['comment'][-1].replace('\n', ' ') # single quotes break command line format - remove comment = comment.replace("'", ' ') accept_terms = (accepted['accept_terms'][-1].strip().lower() in ('1', 'o', 'y', 't', 'on', 'yes', 'true')) 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 accept_terms: output_objects.append({ 'object_type': 'error_text', 'text': 'You must accept the terms of use in sign up!' }) output_objects.append({ 'object_type': 'link', 'destination': 'javascript:history.back();', 'class': 'genericbutton', 'text': "Try again" }) return (output_objects, returnvalues.CLIENT_ERROR) is_diku_email = False is_diku_org = False if email.find('@diku.dk') != -1: is_diku_email = True if 'DIKU' == org.upper(): # Consistent upper casing org = org.upper() is_diku_org = True if is_diku_org != is_diku_email: output_objects.append({ 'object_type': 'error_text', 'text': '''Illegal email and organization combination: Please read and follow the instructions in red on the request page! If you are a DIKU student with only a @*.ku.dk address please just use KU as organization. As long as you state that you want the certificate for DIKU purposes in the comment field, you will be given access to the necessary resources anyway. ''' }) return (output_objects, returnvalues.CLIENT_ERROR) try: distinguished_name_to_user(cert_id) except: output_objects.append({ 'object_type': 'error_text', 'text': '''Illegal Distinguished name: Please note that the distinguished name must be a valid certificate DN with multiple "key=val" fields separated by "/". ''' }) return (output_objects, returnvalues.CLIENT_ERROR) user_dict = { 'distinguished_name': cert_id, 'full_name': cert_name, 'organization': org, 'state': state, 'country': country, 'email': email, 'password': '', 'comment': '%s: %s' % ('Existing certificate', comment), 'expire': default_account_expire(configuration, 'cert'), 'openid_names': [], 'auth': ['extcert'], } fill_distinguished_name(user_dict) user_id = user_dict['distinguished_name'] if configuration.user_openid_providers and configuration.user_openid_alias: user_dict['openid_names'] += \ [user_dict[configuration.user_openid_alias]] logger.info('got extcert request: %s' % user_dict) # If server allows automatic addition of users with a CA validated cert # we create the user immediately and skip mail if configuration.auto_add_cert_user: fill_user(user_dict) # Now all user fields are set and we can begin adding the user db_path = os.path.join(configuration.mig_server_home, user_db_filename) try: create_user(user_dict, configuration.config_file, db_path, ask_renew=False) except Exception as err: logger.error('Failed to create user with existing cert %s: %s' % (cert_id, err)) output_objects.append({ 'object_type': 'error_text', 'text': '''Could not create the user account for you: Please report this problem to the site administrators (%s).''' % admin_email }) return (output_objects, returnvalues.SYSTEM_ERROR) output_objects.append({ 'object_type': 'text', 'text': '''Created the user account for you: Please use the navigation menu to the left to proceed using it. ''' }) return (output_objects, returnvalues.OK) # Without auto add we end here and go through the mail-to-admins procedure req_path = None try: (os_fd, req_path) = tempfile.mkstemp(dir=user_pending) os.write(os_fd, dumps(user_dict)) os.close(os_fd) except Exception as err: logger.error('Failed to write existing certificate request to %s: %s' % (req_path, err)) output_objects.append({ 'object_type': 'error_text', 'text': """Request could not be sent to site administrators. Please contact them manually on %s if this error persists.""" % admin_email }) return (output_objects, returnvalues.SYSTEM_ERROR) logger.info('Wrote existing certificate sign up request to %s' % req_path) tmp_id = req_path.replace(user_pending, '') user_dict['tmp_id'] = tmp_id mig_user = os.environ.get('USER', 'mig') helper_commands = user_manage_commands(configuration, mig_user, req_path, user_id, user_dict, 'cert') user_dict.update(helper_commands) user_dict['site'] = configuration.short_title user_dict['vgrid_label'] = configuration.site_vgrid_label user_dict['vgridman_links'] = generate_https_urls( configuration, '%(auto_base)s/%(auto_bin)s/vgridman.py', {}) email_header = '%s sign up request for %s' % \ (configuration.short_title, cert_id) email_msg = \ """ Received an existing certificate sign up request with certificate data * Distinguished Name: %(distinguished_name)s * Full Name: %(full_name)s * Organization: %(organization)s * State: %(state)s * Country: %(country)s * Email: %(email)s * Comment: %(comment)s * Expire: %(expire)s Command to create user on %(site)s server: %(command_user_create)s Finally add the user %(distinguished_name)s to any relevant %(vgrid_label)ss using one of the management links: %(vgridman_links)s --- Command to reject user account request on %(site)s server: %(command_user_reject)s Command to suspend user on %(site)s server: %(command_user_suspend)s Command to delete user again on %(site)s server: %(command_user_delete)s --- """ % user_dict logger.info('Sending email: to: %s, header: %s, msg: %s, smtp_server: %s' % (admin_email, email_header, email_msg, smtp_server)) if not send_email(admin_email, email_header, email_msg, logger, configuration): output_objects.append({ 'object_type': 'error_text', 'text': """An error occured trying to send the email requesting the sign up with an existing certificate. Please email the site administrators (%s) manually and include the session ID: %s""" % (admin_email, tmp_id) }) return (output_objects, returnvalues.SYSTEM_ERROR) output_objects.append({ 'object_type': 'text', 'text': """Request sent to site administrators: Your request for a %s user account with your existing certificate will be verified and handled as soon as possible, so please be patient. In case of inquiries about this request, please email the site administrators (%s) and include the session ID: %s""" % (configuration.short_title, admin_email, tmp_id) }) return (output_objects, returnvalues.OK)