def restore_sysadmin_password_raw(connect, current_password, original_password, exclude_list): if current_password == original_password: LOG.info( 'Current password is the same as the original password?!, do nothing' ) return for n in range(1, MAX_NUM_PASSWORDS_TRACKED + 1): new_password = security_helper.gen_linux_password( exclude_list=exclude_list, length=PASSWORD_LEGNTH) exclude_list.append(new_password) LOG.info('chaning password {} times: from:{} to:{}\n'.format( n, current_password, new_password)) change_password(connect, current_password, new_password) HostLinuxUser.set_password(new_password) current_password = new_password LOG.info('Restore password of sysadmin to:{}'.format(original_password)) change_password(connect, current_password, original_password) HostLinuxUser.set_password(original_password) LOG.info( 'Password for sysadmin is restored to:{}'.format(original_password))
def setup_testcase_config(testcase_config, lab=None, natbox=None): fip_error = 'A valid IPv4 OAM floating IP has to be specified via ' \ 'cmdline option --lab=<oam_floating_ip>, ' \ 'or testcase config file has to be provided via ' \ '--testcase-config with oam_floating_ip ' \ 'specified under auth_platform section.' if not testcase_config: if not lab: raise ValueError(fip_error) return lab, natbox testcase_config = os.path.expanduser(testcase_config) auth_section = 'auth' guest_image_section = 'guest_image' guest_networks_section = 'guest_networks' guest_keypair_section = 'guest_keypair' natbox_section = 'natbox' config = configparser.ConfigParser() config.read(testcase_config) # # Update global variables for auth section # # Update OAM floating IP if lab: fip = lab.get('floating ip') config.set(auth_section, 'oam_floating_ip', fip) else: fip = config.get(auth_section, 'oam_floating_ip', fallback='').strip() lab = get_lab_dict(fip) if __get_ip_version(fip) != 4: raise ValueError(fip_error) # controller-0 oam ip is updated with best effort if a valid IPv4 IP is # provided if not lab.get('controller-0 ip') and config.get( auth_section, 'controller0_oam_ip', fallback='').strip(): con0_ip = config.get(auth_section, 'controller0_oam_ip').strip() if __get_ip_version(con0_ip) == 4: lab['controller-0 ip'] = con0_ip else: LOG.info( "controller0_oam_ip specified in testcase config file is not " "a valid IPv4 address. Ignore.") # Update linux user credentials if config.get(auth_section, 'linux_username', fallback='').strip(): HostLinuxUser.set_user( config.get(auth_section, 'linux_username').strip()) if config.get(auth_section, 'linux_user_password', fallback='').strip(): HostLinuxUser.set_password( config.get(auth_section, 'linux_user_password').strip()) # Update openstack keystone user credentials auth_dict_map = { 'platform_admin': 'admin_platform', 'admin': 'admin', 'test1': 'tenant1', 'test2': 'tenant2', } for conf_prefix, dict_name in auth_dict_map.items(): kwargs = {} default_auth = Tenant.get(dict_name) conf_user = config.get(auth_section, '{}_username'.format(conf_prefix), fallback='').strip() conf_password = config.get(auth_section, '{}_password'.format(conf_prefix), fallback='').strip() conf_project = config.get(auth_section, '{}_project_name'.format(conf_prefix), fallback='').strip() conf_domain = config.get(auth_section, '{}_domain_name'.format(conf_prefix), fallback='').strip() conf_keypair = config.get(auth_section, '{}_nova_keypair'.format(conf_prefix), fallback='').strip() if conf_user and conf_user != default_auth.get('user'): kwargs['username'] = conf_user if conf_password and conf_password != default_auth.get('password'): kwargs['password'] = conf_password if conf_project and conf_project != default_auth.get('tenant'): kwargs['tenant'] = conf_project if conf_domain and conf_domain != default_auth.get('domain'): kwargs['domain'] = conf_domain if conf_keypair and conf_keypair != default_auth.get('nova_keypair'): kwargs['nova_keypair'] = conf_keypair if kwargs: Tenant.update(dict_name, **kwargs) # # Update global variables for natbox section # natbox_host = config.get(natbox_section, 'natbox_host', fallback='').strip() natbox_user = config.get(natbox_section, 'natbox_user', fallback='').strip() natbox_password = config.get(natbox_section, 'natbox_password', fallback='').strip() natbox_prompt = config.get(natbox_section, 'natbox_prompt', fallback='').strip() if natbox_host and (not natbox or natbox_host != natbox['ip']): natbox = get_natbox_dict(natbox_host, user=natbox_user, password=natbox_password, prompt=natbox_prompt) # # Update global variables for guest_image section # img_file_dir = config.get(guest_image_section, 'img_file_dir', fallback='').strip() glance_image_name = config.get(guest_image_section, 'glance_image_name', fallback='').strip() img_file_name = config.get(guest_image_section, 'img_file_name', fallback='').strip() img_disk_format = config.get(guest_image_section, 'img_disk_format', fallback='').strip() min_disk_size = config.get(guest_image_section, 'min_disk_size', fallback='').strip() img_container_format = config.get(guest_image_section, 'img_container_format', fallback='').strip() image_ssh_user = config.get(guest_image_section, 'image_ssh_user', fallback='').strip() image_ssh_password = config.get(guest_image_section, 'image_ssh_password', fallback='').strip() if img_file_dir and img_file_dir != GuestImages.DEFAULT['image_dir']: # Update default image file directory img_file_dir = os.path.expanduser(img_file_dir) if not os.path.isabs(img_file_dir): raise ValueError( "Please provide a valid absolute path for img_file_dir " "under guest_image section in testcase config file") GuestImages.DEFAULT['image_dir'] = img_file_dir if glance_image_name and glance_image_name != GuestImages.DEFAULT['guest']: # Update default glance image name GuestImages.DEFAULT['guest'] = glance_image_name if glance_image_name not in GuestImages.IMAGE_FILES: # Add guest image info to consts.stx.GuestImages if not (img_file_name and img_disk_format and min_disk_size): raise ValueError( "img_file_name and img_disk_format under guest_image " "section have to be " "specified in testcase config file") img_container_format = img_container_format if \ img_container_format else 'bare' GuestImages.IMAGE_FILES[glance_image_name] = \ (None, min_disk_size, img_file_name, img_disk_format, img_container_format) # Add guest login credentials Guest.CREDS[glance_image_name] = { 'user': image_ssh_user if image_ssh_user else 'root', 'password': image_ssh_password if image_ssh_password else None, } # # Update global variables for guest_keypair section # natbox_keypair_dir = config.get(guest_keypair_section, 'natbox_keypair_dir', fallback='').strip() private_key_path = config.get(guest_keypair_section, 'private_key_path', fallback='').strip() if natbox_keypair_dir: natbox_keypair_path = os.path.join( natbox_keypair_dir, 'keyfile_{}.pem'.format(lab['short_name'])) ProjVar.set_var(NATBOX_KEYFILE_PATH=natbox_keypair_path) if private_key_path: ProjVar.set_var(STX_KEYFILE_PATH=private_key_path) # # Update global variables for guest_networks section # net_name_patterns = { 'mgmt': config.get(guest_networks_section, 'mgmt_net_name_pattern', fallback='').strip(), 'data': config.get(guest_networks_section, 'data_net_name_pattern', fallback='').strip(), 'internal': config.get(guest_networks_section, 'internal_net_name_pattern', fallback='').strip(), 'external': config.get(guest_networks_section, 'external_net_name_pattern', fallback='').strip() } for net_type, net_name_pattern in net_name_patterns.items(): if net_name_pattern: Networks.set_neutron_net_patterns( net_type=net_type, net_name_pattern=net_name_pattern) return lab, natbox
def test_sysadmin_aging_and_swact(swact): """ Test password aging. Args: Test Steps: 1 change the aging setting, forcing current password expired, new password be set and required by next login 2 verify the new password is required upon login to the floating IP Returns: """ global _host_users LOG.tc_step('Change the aging settings of sysadmin') if 'sysadmin' != HostLinuxUser.get_user(): skip('Current User:{} is not sysadmin'.format( HostLinuxUser.get_user())) return user = '******' original_password = HostLinuxUser.get_password() active_controller = ControllerClient.get_active_controller() active_controller_name = system_helper.get_active_controller_name() host = lab_info.get_lab_floating_ip() _host_users[('active-controller', 'sysadmin')] = [original_password] LOG.info('Closing ssh connection to the active controller\n') active_controller.flush() active_controller.close() wait_time = 10 LOG.info( 'wait for {} seconds after closing the ssh connect to the active-controller' .format(wait_time)) time.sleep(wait_time) # command = 'chage -d 0 -M 0 sysadmin' # this is from the test plan # sudo passwd -e sysadmin command = 'sudo passwd -e sysadmin' LOG.info('changing password aging using command:\n{}'.format(command)) connect = log_in_raw(host, user, original_password) LOG.info('sudo execute:{}\n'.format(command)) code, output = execute_sudo_cmd(connect, command, original_password, expecting_fail=False) # code, output = active_controller.exec_sudo_cmd(command) LOG.info( 'OK, aging settings of sysadmin was successfully changed with command:\n{}\ncode:{}, output:{}' .format(command, code, output)) LOG.tc_step('Verify new password needs to be set upon login') exclude_list = [original_password] # verify password was expired new_password = security_helper.gen_linux_password( exclude_list=exclude_list, length=PASSWORD_LEGNTH) set_password = first_login_to_floating_ip(user, original_password, new_password)[1] if set_password != new_password: message = 'first time login did not ask for new password:{}, ' \ 'current password should still been in effective\n'.format(new_password, original_password) LOG.warn(message) assert False, message # and reset with new password new_password = set_password if new_password != original_password: _host_users[('active-controller', 'sysadmin')].append(new_password) HostLinuxUser.set_password(new_password) exclude_list.append(new_password) LOG.info('OK, new password was required and logged in\n') # reconnect after set new password LOG.info('reconnect to the active controller') host = lab_info.get_lab_floating_ip() connect = log_in_raw(host, user, new_password) cmd = 'hostname; id; date' LOG.info('attempt to run cmd:{}\n'.format(cmd)) code, output = execute_cmd(connect, cmd) LOG.info('output:\n{}\n, code:{}, cmd:{}\n'.format(output, code, cmd)) # perform swact and verify swact is working wait_time = 300 LOG.info('wait for {} seconds after aging settings been modified'.format( wait_time)) time.sleep(wait_time) if swact == 'swact': LOG.tc_step('Swact host') swact_host_after_reset_sysadmin_raw(connect, active_controller_name) LOG.info('OK, host swact') LOG.info('Closing raw ssh connection to the active controller\n') connect.logout() wait_time = 180 LOG.info('wait for {} after swact and closing own ssh connection'.format( wait_time)) time.sleep(wait_time) # reconnect to active after swact LOG.info('reconnect to the active controller') host = lab_info.get_lab_floating_ip() connect = log_in_raw(host, user, new_password) LOG.tc_step('Restore the password ') # restore_sysadmin_password_raw(connect, new_password, original_password, exclude_list=exclude_list) restore_sysadmin_password_raw(connect, current_password=new_password, original_password="******", exclude_list=exclude_list) HostLinuxUser.set_password(original_password) LOG.info('Close the connection to {} as user:{} with password:{}'.format( host, user, original_password)) connect.close() LOG.info( 'reconnect to the active controller using ControllerClient.get_active_controller()\n' ) active_controller.connect()
def change_linux_user_password(password, new_password, user=None, host=None): if not user: user = HostLinuxUser.get_user() LOG.info( 'Attempt to change password, from password:{}, to new-password:{}, ' 'on host:{}'.format( password, new_password, host)) input_outputs = ( ( 'passwd', (r'\(current\) UNIX password: '******'New password: '******': Authentication token manipulation error', EOF,), ), ( new_password, ('Retype new password:'******'BAD PASSWORD: The password is too similar to the old one', 'BAD PASSWORD: No password supplied', 'passwd: Have exhausted maximum number of retries for service', EOF, ), ), ( new_password, (': all authentication tokens updated successfully.', Prompt.CONTROLLER_PROMPT,), (), ), ) conn_to_ac = ControllerClient.get_active_controller() initial_prompt = r'.*{}\:~\$ '.format(host) LOG.info('Will login as user:"******", password:"******", to host:"{}"'.format( user, password, host)) passed = True try: conn = SSHFromSSH(conn_to_ac, host, user, password, force_password=True, initial_prompt=initial_prompt) except: passed = False return passed, new_password try: conn.connect(retry=False, use_password=True) for cmd, expected, errors in input_outputs: # conn.flush() LOG.info("Send '{}'\n".format(cmd)) conn.send(cmd) blob_list = list(expected) + list(errors) LOG.info("Expect: {}\n".format(blob_list)) index = conn.expect(blob_list=blob_list) LOG.info('returned index:{}\n'.format(index)) if len(expected) <= index: passed = False break except Exception as e: LOG.warn( 'Caught exception when connecting to host:{} as user:{} with ' 'pasword:{}\n{}\n'.format( host, user, password, e)) raise finally: pass # TODO: close this connection will lead EOF error in ssh.py if # invoked in fixture cleanup handler conn.close() if user == HostLinuxUser.get_user(): conn = ControllerClient.get_active_controller() if conn.is_connected(): conn.close() conn.password = new_password conn.connect() HostLinuxUser.set_password(new_password) # flush the output to the cli so the next cli is correctly registered # conn.flush() LOG.info( 'Successfully changed password from:\n{}\nto:{} for user:{} on ' 'host:{}'.format(password, new_password, user, host)) return passed, new_password