def delete_account(self, user): """ Delete the 'user'. Clear utmp first, to avoid error. Removes the /etc/sudoers.d/waagent file. """ userentry = None try: userentry = pwd.getpwnam(user) except (EnvironmentError, KeyError): pass if userentry is None: logger.error("DeleteAccount: " + user + " not found.") return uidmin = None try: if os.path.isfile("/etc/login.defs"): uidmin = int( ext_utils.get_line_starting_with("UID_MIN", "/etc/login.defs").split()[1]) except (ValueError, KeyError, AttributeError, EnvironmentError): pass if uidmin is None: uidmin = 100 if userentry[2] < uidmin: logger.error( "DeleteAccount: " + user + " is a system user. Will not delete account.") return # empty contents of utmp to prevent error if we are the 'user' deleted ext_utils.run_command_and_write_stdout_to_file(['echo'], '/var/run/utmp') ext_utils.run(['rmuser', '-y', user], chk_err=False) try: os.remove(self.sudoers_dir_base + "/sudoers.d/waagent") except EnvironmentError: pass return
def test_code_injection2(self): self.setup() self.addCleanup(self.cleanup) # failure cases out_file = self.get_random_filename() exit_code = ext_utils.run_command_and_write_stdout_to_file( "echo hello; echo world", out_file) self.assertNotEqual(0, exit_code, "exit code != 0") out_file = self.get_random_filename() exit_code = ext_utils.run_command_and_write_stdout_to_file( ["echo hello; echo world"], out_file) self.assertNotEqual(0, exit_code, "exit code != 0") # success case out_file = self.get_random_filename() exit_code = ext_utils.run_command_and_write_stdout_to_file( ["echo", "hello", ";", "echo", "world"], out_file) self.assertEqual(0, exit_code, "exit code == 0") file_contents = ext_utils.get_file_contents(out_file) self.assertEqual("hello ; echo world\n", file_contents, "unexpected output") out_file = self.get_random_filename() exit_code = ext_utils.run_command_and_write_stdout_to_file( ["echo", "hello", "world"], out_file) self.assertEqual(0, exit_code, "exit code == 0") file_contents = ext_utils.get_file_contents(out_file) self.assertEqual("hello world\n", file_contents, "unexpected output")
def create_account(self, user, password, expiration, thumbprint): """ Create a user account, with 'user', 'password', 'expiration', ssh keys and sudo permissions. Returns None if successful, error string on failure. """ userentry = None try: userentry = pwd.getpwnam(user) except (EnvironmentError, KeyError): pass uidmin = None try: uidmin = int(ext_utils.get_line_starting_with("UID_MIN", "/etc/login.defs").split()[1]) except (ValueError, KeyError, AttributeError, EnvironmentError): pass if uidmin is None: uidmin = 100 if userentry is not None and userentry[2] < uidmin and userentry[2] != self.CORE_UID: logger.error( "CreateAccount: " + user + " is a system user. Will not set password.") return "Failed to set password for system user: "******" (0x06)." if userentry is None: command = ['useradd', '--create-home', '--password', '*', user] if expiration is not None: command += ['--expiredate', expiration.split('.')[0]] if ext_utils.run(command): logger.error("Failed to create user account: " + user) return "Failed to create user account: " + user + " (0x07)." else: logger.log("CreateAccount: " + user + " already exists. Will update password.") if password is not None: self.change_password(user, password) try: if password is None: ext_utils.set_file_contents("/etc/sudoers.d/waagent", user + " ALL = (ALL) NOPASSWD: ALL\n") else: ext_utils.set_file_contents("/etc/sudoers.d/waagent", user + " ALL = (ALL) ALL\n") os.chmod("/etc/sudoers.d/waagent", 0o440) except EnvironmentError: logger.error("CreateAccount: Failed to configure sudo access for user.") return "Failed to configure sudo privileges (0x08)." home = self.get_home() if thumbprint is not None: ssh_dir = home + "/" + user + "/.ssh" ext_utils.create_dir(ssh_dir, user, 0o700) pub = ssh_dir + "/id_rsa.pub" prv = ssh_dir + "/id_rsa" ext_utils.run_command_and_write_stdout_to_file(['ssh-keygen', '-y', '-f', thumbprint + '.prv'], pub) ext_utils.set_file_contents(prv, ext_utils.get_file_contents(thumbprint + ".prv")) for f in [pub, prv]: os.chmod(f, 0o600) ext_utils.change_owner(f, user) ext_utils.set_file_contents(ssh_dir + "/authorized_keys", ext_utils.get_file_contents(pub)) ext_utils.change_owner(ssh_dir + "/authorized_keys", user) logger.log("Created user account: " + user) return None
def ssh_deploy_public_key(self, fprint, path): """ Generic sshDeployPublicKey - over-ridden in some concrete Distro classes due to minor differences in openssl packages deployed """ keygen_retcode = ext_utils.run_command_and_write_stdout_to_file( ['ssh-keygen', '-i', '-m', 'PKCS8', '-f', fprint], path) if keygen_retcode: return 1 else: return 0
def _set_user_account_pub_key(protect_settings, hutil): ovf_xml = None ovf_env = None try: ovf_xml = ext_utils.get_file_contents('/var/lib/waagent/ovf-env.xml') ovf_env = ovf_utils.OvfEnv.parse(ovf_xml, Configuration) except (EnvironmentError, ValueError, KeyError, AttributeError): pass if ovf_xml is None or ovf_env is None: # default ovf_env with empty data ovf_env = ovf_utils.OvfEnv() logger.log("could not load ovf-env.xml") # user name must be provided if set ssh key or password if not protect_settings or 'username' not in protect_settings: return user_name = protect_settings['username'] user_pass = protect_settings.get('password') cert_txt = protect_settings.get('ssh_key') expiration = protect_settings.get('expiration') no_convert = False if not user_pass and not cert_txt and not ovf_env.SshPublicKeys: raise Exception("No password or ssh_key is specified.") if user_pass is not None and len(user_pass) == 0: user_pass = None hutil.log("empty passwords are not allowed, ignoring password reset") # Reset user account and password, password could be empty sudoers = _get_other_sudoers(user_name) error_string = MyDistro.create_account(user_name, user_pass, expiration, None) _save_other_sudoers(sudoers) if error_string is not None: err_msg = "Failed to create the account or set the password" ext_utils.add_extension_event(name=hutil.get_name(), op=constants.WALAEventOperation.Enable, is_success=False, message="(02101)" + err_msg) raise Exception(err_msg + " with " + error_string) hutil.log("Succeeded in creating the account or setting the password.") # Allow password authentication if user_pass is provided if user_pass is not None: ext_utils.add_extension_event(name=hutil.get_name(), op="scenario", is_success=True, message="create-user-with-password") _allow_password_auth() # Reset ssh key with the new public key passed in or reuse old public key. if cert_txt: if cert_txt and cert_txt.strip().lower().startswith("ssh-rsa"): no_convert = True try: pub_path = os.path.join('/home/', user_name, '.ssh', 'authorized_keys') ovf_env.UserName = user_name if no_convert: if cert_txt: pub_path = ovf_env.prepare_dir(pub_path, MyDistro) final_cert_txt = cert_txt if not cert_txt.endswith("\n"): final_cert_txt = final_cert_txt + "\n" ext_utils.append_file_contents(pub_path, final_cert_txt) MyDistro.set_se_linux_context( pub_path, 'unconfined_u:object_r:ssh_home_t:s0') ext_utils.change_owner(pub_path, user_name) ext_utils.add_extension_event(name=hutil.get_name(), op="scenario", is_success=True, message="create-user") hutil.log("Succeeded in resetting ssh_key.") else: err_msg = "Failed to reset ssh key because the cert content is empty." ext_utils.add_extension_event( name=hutil.get_name(), op=constants.WALAEventOperation.Enable, is_success=False, message="(02100)" + err_msg) else: # do the certificate conversion # we support PKCS8 certificates besides ssh-rsa public keys _save_cert_str_as_file(cert_txt, 'temp.crt') pub_path = ovf_env.prepare_dir(pub_path, MyDistro) retcode = ext_utils.run_command_and_write_stdout_to_file([ constants.Openssl, 'x509', '-in', 'temp.crt', '-noout', '-pubkey' ], "temp.pub") if retcode > 0: raise Exception("Failed to generate public key file.") MyDistro.ssh_deploy_public_key('temp.pub', pub_path) os.remove('temp.pub') os.remove('temp.crt') ext_utils.add_extension_event(name=hutil.get_name(), op="scenario", is_success=True, message="create-user") hutil.log("Succeeded in resetting ssh_key.") except Exception as e: hutil.log(str(e)) ext_utils.add_extension_event( name=hutil.get_name(), op=constants.WALAEventOperation.Enable, is_success=False, message="(02100)Failed to reset ssh key.") raise e