def main(argv): del argv # Unused. if flags.FLAGS.mysql_username is None: raise ValueError("--mysql_username has to be specified.") # Generate server and client configs. server_conf_path, client_conf_path = self_contained_components.InitConfigs( flags.FLAGS.mysql_database, mysql_username=flags.FLAGS.mysql_username, mysql_password=flags.FLAGS.mysql_password, logging_path=flags.FLAGS.logging_path, osquery_path=flags.FLAGS.osquery_path) # Start all remaining server components. # Start a background thread that kills the main process if one of the # server subprocesses dies. server_processes = self_contained_components.StartServerProcesses( server_conf_path) self_contained_components.DieIfSubProcessDies(server_processes) api_port = api_helpers.GetAdminUIPortFromConfig(server_conf_path) grrapi = api_helpers.WaitForAPIEndpoint(api_port) # Start the client. preliminary_client_p = self_contained_components.StartClientProcess( client_conf_path) # Wait for the client to enroll and get its id. client_id = api_helpers.WaitForClientToEnroll(grrapi) print("Found client id: %s" % client_id) # Python doesn't guarantee the process name of processes started by the Python # interpreter. They may vary from platform to platform. In order to ensure # that Client.binary_name config setting matches the actual process name, # let's get the name via psutil, kill the client and set the # Config.binary_name explicitly. client_binary_name = str(psutil.Process(preliminary_client_p.pid).name()) api_helpers.KillClient(grrapi, client_id) preliminary_client_p.wait() print("Starting the client with Client.binary_name=%s" % client_binary_name) client_p = self_contained_components.StartClientProcess( client_conf_path, {"Client.binary_name": client_binary_name}) # Start a background thread that kills the main process if # client subprocess dies. self_contained_components.DieIfSubProcessDies([client_p]) # Run the test suite against the enrolled client. self_contained_components.RunEndToEndTests( client_id, server_conf_path, tests=flags.FLAGS.tests, manual_tests=flags.FLAGS.manual_tests) print("RunEndToEndTests execution succeeded.") sys.exit(0)
def main(argv): del argv # Unused. if flags.FLAGS.mysql_username is None: raise ValueError("--mysql_username has to be specified.") # Generate server and client configs. grr_configs = self_contained_components.InitGRRConfigs( flags.FLAGS.mysql_database, mysql_username=flags.FLAGS.mysql_username, mysql_password=flags.FLAGS.mysql_password, logging_path=flags.FLAGS.logging_path) print("Building the template.") template_path = self_contained_components.RunBuildTemplate( grr_configs.server_config, component_options={"Logging.verbose": True}) print("Repack %s." % template_path) installer_path = self_contained_components.RunRepackTemplate( grr_configs.server_config, template_path) version_overrides = { "Source.version_major": 9, "Source.version_minor": 9, "Source.version_revision": 9, "Source.version_release": 9, "Source.version_string": "9.9.9.9", "Source.version_numeric": 9999, "Template.version_major": 9, "Template.version_minor": 9, "Template.version_revision": 9, "Template.version_release": 9, "Template.version_string": "9.9.9.9", "Template.version_numeric": 9999, } print("Building next ver. template.") next_ver_template_path = self_contained_components.RunBuildTemplate( grr_configs.server_config, component_options=version_overrides, version_ini=_HIGHEST_VERSION_INI) print("Repack next ver. %s." % template_path) next_ver_installer_path = self_contained_components.RunRepackTemplate( grr_configs.server_config, next_ver_template_path, component_options=version_overrides) print("First installer ready: %s. Next ver. installer ready: %s." % (installer_path, next_ver_installer_path)) print("Starting the server.") # Start all remaining server components. # Start a background thread that kills the main process if one of the # server subprocesses dies. server_processes = self_contained_components.StartServerProcesses(grr_configs) self_contained_components.DieIfSubProcessDies(server_processes) api_port = api_helpers.GetAdminUIPortFromConfig(grr_configs.server_config) grrapi = api_helpers.WaitForAPIEndpoint(api_port) print("Installing the client.") system = platform.system().lower() if system == "linux": distro_id = distro.id() if distro_id in ["ubuntu", "debian"]: subprocess.check_call( ["apt", "install", "--reinstall", "-y", installer_path]) elif distro_id in ["centos", "rhel", "fedora"]: subprocess.check_call(["rpm", "-Uvh", installer_path]) else: raise RuntimeError("Unsupported linux distro: %s" % distro_id) elif system == "windows": subprocess.check_call([installer_path]) elif system == "darwin": subprocess.check_call(["installer", "-pkg", installer_path, "-target", "/"]) else: raise RuntimeError("Unsupported platform for self-update tests: %s" % system) # Wait for the client to enroll and get its id. client_id = api_helpers.WaitForClientToEnroll(grrapi) print("Found client id: %s" % client_id) print("Waiting for the client to report the initial version.") prev_version = api_helpers.WaitForClientVersionGreaterThan( grrapi.Client(client_id), 0) binary_id = self_contained_components.RunUploadExe(grr_configs.server_config, next_ver_installer_path, system) args = grrapi.types.CreateFlowArgs(flow_name="UpdateClient") args.binary_path = binary_id f = grrapi.Client(client_id).CreateFlow(name="UpdateClient", args=args) try: # Timeout has to be rather significant, since at the moment installers # are uploaded in chunks of 512Kb, each chunk requiring a round-trip # to/from the client. f.WaitUntilDone(timeout=180) print("Update flow finished successfully. This should never happen: " "the client should have been restarted.") sys.exit(-1) except errors.PollTimeoutError: print("Update flow timed out. This shouldn't happen: the flow should " "fail explicitly due to a client restart.") sys.exit(-1) except errors.FlowFailedError: print("Update flow failed (expected behavior, as the client got " "restarted).") print("Update flow details:") print(f.Get().data) print("Waiting for the client to report the updated version.") api_helpers.WaitForClientVersionGreaterThan( grrapi.Client(client_id), prev_version) print("Self-update test successful!") sys.exit(0)
def main(argv): grr_configs = self_contained_components.InitGRRConfigs( flags.FLAGS.mysql_database, mysql_username=flags.FLAGS.mysql_username, mysql_password=flags.FLAGS.mysql_password, logging_path=flags.FLAGS.logging_path, with_fleetspeak=True) fleetspeak_configs = self_contained_components.InitFleetspeakConfigs( grr_configs, flags.FLAGS.fleetspeak_mysql_database, mysql_username=flags.FLAGS.mysql_username, mysql_password=flags.FLAGS.mysql_password) server_processes = self_contained_components.StartServerProcesses( grr_configs=grr_configs, fleetspeak_configs=fleetspeak_configs) api_port = api_helpers.GetAdminUIPortFromConfig(grr_configs.server_config) grr_api = api_helpers.WaitForAPIEndpoint(api_port) if list(grr_api.SearchClients()): raise Exception("This tests expects to be run on an empty database.") client_p = self_contained_components.StartClientProcess( grr_configs=grr_configs, fleetspeak_configs=fleetspeak_configs) client_id = api_helpers.WaitForClientToEnroll(grr_api) print("client_id is", client_id) client_proc_before = FindGrrClientProcess(grr_configs.client_config) print("GRR process has process ID {}.".format(client_proc_before.pid)) print("Running Interrogate flow 1.") result = RunInterrogate(grr_api, client_id) print("Interrogate flow 1 finished with result {}.".format(result)) print("Running RestartFleetspeakGrrService().") self_contained_components.RunApiShellRawAccess( grr_configs.server_config, "grrapi.root.Client(\"{}\").RestartFleetspeakGrrService()".format( client_id)) print("Finished RestartFleetspeakGrrService().") # We have to wait for the restart to finish. # Killing the GRR service while a flow is running might make the flow hang. # The GRR client sends the reply of an action to fleetspeak, then deletes # the action from the transaction log. However, fleetspeak buffers the reply # in memory for up to one second. If the GRR client gets killed in this # time window, the reply is lost. time.sleep(10) client_proc_after = FindGrrClientProcess(grr_configs.client_config) print("GRR process has process ID {} after restart.".format( client_proc_before.pid)) if client_proc_before.pid == client_proc_after.pid: raise Exception("Process ID of GRR process didn't change as expected. " "Before: {}. After: {}.".format( client_proc_before.pid, client_proc_after.pid)) print("Running Interrogate flow 2.") result = RunInterrogate(grr_api, client_id) print("Interrogate flow 2 finished with result {}.".format(result)) if client_p.poll() is not None: raise Exception( "Fleetspeak client process is expected to run, but it terminated.") # With force=False the fleetspeak client performs a graceful shutdown. print("Running KillFleetspeak(force=False).") self_contained_components.RunApiShellRawAccess( grr_configs.server_config, "grrapi.root.Client(\"{}\").KillFleetspeak(force=False)".format( client_id)) print("Finished KillFleetspeak(force=False).") print("Waiting for fleetspeak client to terminate.") client_p.wait(5) print("Fleetspeak client terminated.") print("Restarting fleetspeak client.") client_p = self_contained_components.StartClientProcess( grr_configs=grr_configs, fleetspeak_configs=fleetspeak_configs) print("Running Interrogate flow 3.") result = RunInterrogate(grr_api, client_id) print("Interrogate flow 3 finished with result {}.".format(result)) if client_p.poll() is not None: raise Exception( "Fleetspeak client process is expected to run, but it terminated.") # With force=True the fleetspeak clients just exits. print("Running KillFleetspeak(force=True).") self_contained_components.RunApiShellRawAccess( grr_configs.server_config, "grrapi.root.Client(\"{}\").KillFleetspeak(force=True)".format( client_id)) print("Finished KillFleetspeak(force=True).") print("Waiting for fleetspeak client to terminate.") client_p.wait(5) print("Fleetspeak client terminated.") print("Restarting fleetspeak client.") client_p = self_contained_components.StartClientProcess( grr_configs=grr_configs, fleetspeak_configs=fleetspeak_configs) print("Running Interrogate flow 4.") result = RunInterrogate(grr_api, client_id) print("Interrogate flow 4 finished with result {}.".format(result)) print("Finished.") sys.exit(0)