def ManageBinaries(config=None, token=None): """Repack templates into installers.""" print("\nStep 4: Repackaging clients with new configuration.") redownload_templates = False repack_templates = False if flags.FLAGS.noprompt: redownload_templates = flags.FLAGS.redownload_templates repack_templates = not flags.FLAGS.norepack_templates else: redownload_templates = RetryBoolQuestion( "Server debs include client templates. Re-download templates?", False) repack_templates = RetryBoolQuestion("Repack client templates?", True) if redownload_templates: InstallTemplatePackage() # Build debug binaries, then build release binaries. if repack_templates: repacking.TemplateRepacker().RepackAllTemplates(upload=True, token=token) print("\nInitialization complete, writing configuration.") config.Write() print("Please restart the service for it to take effect.\n\n")
def testRepackAll(self): """Test repacking all binaries.""" self.executables_dir = package.ResourcePath("grr-response-core", "executables") with utils.TempDirectory() as tmp_dir: new_dir = os.path.join(tmp_dir, "grr", "executables") os.makedirs(new_dir) # Copy unzipsfx so it can be used in repacking/ shutil.copy( os.path.join(self.executables_dir, "windows/templates/unzipsfx/unzipsfx-i386.exe"), new_dir) shutil.copy( os.path.join(self.executables_dir, "windows/templates/unzipsfx/unzipsfx-amd64.exe"), new_dir) with test_lib.ConfigOverrider({ "ClientBuilder.executables_dir": new_dir, "ClientBuilder.unzipsfx_stub_dir": new_dir }): repacking.TemplateRepacker().RepackAllTemplates() self.assertEqual( len(glob.glob(os.path.join(new_dir, "installers/*.deb"))), 2) self.assertEqual( len(glob.glob(os.path.join(new_dir, "installers/*.rpm"))), 2) self.assertEqual( len(glob.glob(os.path.join(new_dir, "installers/*.exe"))), 4) self.assertEqual( len(glob.glob(os.path.join(new_dir, "installers/*.pkg"))), 1) # Validate the config appended to the OS X package. zf = zipfile.ZipFile(glob.glob( os.path.join(new_dir, "installers/*.pkg")).pop(), mode="r") fd = zf.open("config.yaml") # We can't load the included build.yaml because the package hasn't been # installed. loaded = yaml.safe_load(fd) loaded.pop("Config.includes") packaged_config = config.CONFIG.MakeNewConfig() data = yaml.safe_dump(loaded) packaged_config.Initialize(parser=config_lib.YamlParser, data=data.decode("utf-8")) packaged_config.Validate( sections=build.ClientRepacker.CONFIG_SECTIONS) repacker = build.ClientRepacker() repacker.ValidateEndConfig(packaged_config)
def FinalizeConfigInit(config, token): """Performs the final steps of config initialization.""" config.Set("Server.initialized", True) print("\nWriting configuration to %s." % config["Config.writeback"]) config.Write() print("Initializing the datastore.") # Reload the config and initialize the GRR database. server_startup.Init() print("\nStep 3: Adding GRR Admin User") try: maintenance_utils.AddUser("admin", labels=["admin"], token=token, password=flags.FLAGS.admin_password) except maintenance_utils.UserError: if flags.FLAGS.noprompt: maintenance_utils.UpdateUser("admin", password=flags.FLAGS.admin_password, add_labels=["admin"], token=token) else: # pytype: disable=wrong-arg-count if ((builtins.input("User 'admin' already exists, do you want to " "reset the password? [yN]: ").upper() or "N") == "Y"): maintenance_utils.UpdateUser("admin", password=True, add_labels=["admin"], token=token) # pytype: enable=wrong-arg-count print("\nStep 4: Repackaging clients with new configuration.") redownload_templates = False repack_templates = False if flags.FLAGS.noprompt: redownload_templates = flags.FLAGS.redownload_templates repack_templates = not flags.FLAGS.norepack_templates else: redownload_templates = RetryBoolQuestion( "Server debs include client templates. Re-download templates?", False) repack_templates = RetryBoolQuestion("Repack client templates?", True) if redownload_templates: InstallTemplatePackage() # Build debug binaries, then build release binaries. if repack_templates: repacking.TemplateRepacker().RepackAllTemplates(upload=True, token=token) print("\nGRR Initialization complete! You can edit the new configuration " "in %s.\n" % config["Config.writeback"]) print("Please restart the service for the new configuration to take " "effect.\n")
def main(args): """Launch the appropriate builder.""" grr_config.CONFIG.AddContext(contexts.CLIENT_BUILD_CONTEXT) if args.subparser_name == "generate_client_config": # We don't need a full init to just build a config. GetClientConfig(args.client_config_output) return # We deliberately use args.context because client_startup.py pollutes # grr_config.CONFIG.context with the running system context. context = FLAGS.context context.append(contexts.CLIENT_BUILD_CONTEXT) client_startup.ClientInit() # Use basic console output logging so we can see what is happening. logger = logging.getLogger() handler = logging.StreamHandler() handler.setLevel(logging.INFO) logger.handlers = [handler] if args.subparser_name == "build": if grr_config.CONFIG.Get("ClientBuilder.fleetspeak_enabled"): if "Target:Darwin" in context: if not args.fleetspeak_service_config: raise RuntimeError( "--fleetspeak_service_config must be provided.") if not grr_config.CONFIG.Get("ClientBuilder.install_dir"): raise RuntimeError( "ClientBuilder.install_dir must be set.") if not grr_config.CONFIG.Get( "ClientBuilder.fleetspeak_plist_path"): raise RuntimeError( "ClientBuilder.fleetspeak_plist_path must be set.") grr_config.CONFIG.Set("ClientBuilder.client_path", "grr_response_client.grr_fs_client") TemplateBuilder().BuildTemplate( context=context, output=args.output, fleetspeak_service_config=args.fleetspeak_service_config) elif args.subparser_name == "repack": if args.debug_build: context.append("DebugClientBuild Context") result_path = repacking.TemplateRepacker().RepackTemplate( args.template, args.output_dir, context=context, sign=args.sign, signed_template=args.signed_template) if not result_path: raise ErrorDuringRepacking(" ".join(sys.argv[:])) elif args.subparser_name == "repack_multiple": # Resolve globs manually on Windows. templates = [] for template in args.templates: if "*" in template: templates.extend(glob.glob(template)) else: # This could go through glob but then we'd swallow errors for # non existing files. templates.append(template) repack_configs = [] for repack_config in args.repack_configs: if "*" in repack_config: repack_configs.extend(glob.glob(repack_config)) else: # This could go through glob but then we'd swallow errors for # non existing files. repack_configs.append(repack_config) MultiTemplateRepacker().RepackTemplates( repack_configs, templates, args.output_dir, config=FLAGS.config, sign=args.sign, signed_template=args.signed_template) elif args.subparser_name == "sign_template": repacking.TemplateRepacker().SignTemplate(args.template, args.output_file, context=context) if not os.path.exists(args.output_file): raise RuntimeError("Signing failed: output not written")
def RepackTemplates(self, repack_configs, templates, output_dir, config=None, sign=False, signed_template=False): """Call repacker in a subprocess.""" pool = multiprocessing.Pool(processes=10) results = [] bulk_sign_installers = False for repack_config in repack_configs: for template in templates: repack_args = ["grr_client_build"] if config: repack_args.extend(["--config", config]) repack_args.extend([ "--secondary_configs", repack_config, "repack", "--template", template, "--output_dir", self.GetOutputDir(output_dir, repack_config) ]) # We only sign exes and rpms at the moment. The others will raise if we # try to ask for signing. passwd = None if sign: if template.endswith(".exe.zip"): # This is for osslsigncode only. if platform.system() != "Windows": passwd = self.GetWindowsPassphrase() repack_args.append("--sign") else: bulk_sign_installers = True if signed_template: repack_args.append("--signed_template") elif template.endswith(".rpm.zip"): bulk_sign_installers = True print("Calling %s" % " ".join(repack_args)) results.append( pool.apply_async(SpawnProcess, (repack_args, ), dict(passwd=passwd))) # Also build debug if it's windows. if template.endswith(".exe.zip"): debug_args = [] debug_args.extend(repack_args) debug_args.append("--debug_build") print("Calling %s" % " ".join(debug_args)) results.append( pool.apply_async(SpawnProcess, (debug_args, ), dict(passwd=passwd))) try: pool.close() # Workaround to handle keyboard kills # http://stackoverflow.com/questions/1408356/keyboard-interrupts-with-pythons-multiprocessing-pool # get will raise if the child raises. for result_obj in results: result_obj.get(9999) pool.join() except KeyboardInterrupt: print("parent received control-c") pool.terminate() except ErrorDuringRepacking: pool.terminate() raise if bulk_sign_installers: to_sign = {} for root, _, files in os.walk(output_dir): for f in files: if f.endswith(".exe"): to_sign.setdefault("windows", []).append(os.path.join(root, f)) elif f.endswith(".rpm"): to_sign.setdefault("rpm", []).append(os.path.join(root, f)) if to_sign.get("windows"): signer = repacking.TemplateRepacker().GetSigner([ "ClientBuilder Context", "Platform:%s" % platform.system(), "Target:Windows" ]) signer.SignFiles(to_sign.get("windows")) if to_sign.get("rpm"): signer = repacking.TemplateRepacker().GetSigner([ "ClientBuilder Context", "Platform:%s" % platform.system(), "Target:Linux", "Target:LinuxRpm" ]) signer.AddSignatureToRPMs(to_sign.get("rpm"))
def main(argv): """Main.""" del argv # Unused. if flags.FLAGS.subparser_name == "version": version = config_server.VERSION["packageversion"] print("GRR configuration updater {}".format(version)) return token = config_updater_util.GetToken() grr_config.CONFIG.AddContext(contexts.COMMAND_LINE_CONTEXT) grr_config.CONFIG.AddContext(contexts.CONFIG_UPDATER_CONTEXT) if flags.FLAGS.subparser_name == "initialize": config_lib.ParseConfigCommandLine() if flags.FLAGS.noprompt: config_updater_util.InitializeNoPrompt(grr_config.CONFIG, token=token) else: config_updater_util.Initialize(grr_config.CONFIG, token=token) return server_startup.Init() try: print("Using configuration %s" % grr_config.CONFIG) except AttributeError: raise RuntimeError("No valid config specified.") if flags.FLAGS.subparser_name == "generate_keys": try: config_updater_util.GenerateKeys( grr_config.CONFIG, overwrite_keys=flags.FLAGS.overwrite_keys) except RuntimeError as e: # GenerateKeys will raise if keys exist and overwrite_keys is not set. print("ERROR: %s" % e) sys.exit(1) grr_config.CONFIG.Write() elif flags.FLAGS.subparser_name == "repack_clients": upload = not flags.FLAGS.noupload repacking.TemplateRepacker().RepackAllTemplates(upload=upload, token=token) elif flags.FLAGS.subparser_name == "show_user": maintenance_utils.ShowUser(flags.FLAGS.username, token=token) elif flags.FLAGS.subparser_name == "update_user": try: maintenance_utils.UpdateUser(flags.FLAGS.username, flags.FLAGS.password, flags.FLAGS.add_labels, flags.FLAGS.delete_labels, token=token) except maintenance_utils.UserError as e: print(e) elif flags.FLAGS.subparser_name == "delete_user": maintenance_utils.DeleteUser(flags.FLAGS.username, token=token) elif flags.FLAGS.subparser_name == "add_user": labels = [] if not flags.FLAGS.noadmin: labels.append("admin") if flags.FLAGS.labels: labels.extend(flags.FLAGS.labels) try: maintenance_utils.AddUser(flags.FLAGS.username, flags.FLAGS.password, labels, token=token) except maintenance_utils.UserError as e: print(e) elif flags.FLAGS.subparser_name == "upload_python": python_hack_root_urn = grr_config.CONFIG.Get("Config.python_hack_root") content = open(flags.FLAGS.file, "rb").read(1024 * 1024 * 30) aff4_path = flags.FLAGS.dest_path platform = flags.FLAGS.platform if not aff4_path: aff4_path = python_hack_root_urn.Add(platform.lower()).Add( os.path.basename(flags.FLAGS.file)) if not str(aff4_path).startswith(str(python_hack_root_urn)): raise ValueError("AFF4 path must start with %s." % python_hack_root_urn) context = ["Platform:%s" % platform.title(), "Client Context"] maintenance_utils.UploadSignedConfigBlob(content, aff4_path=aff4_path, client_context=context, token=token) elif flags.FLAGS.subparser_name == "upload_exe": content = open(flags.FLAGS.file, "rb").read(1024 * 1024 * 30) context = [ "Platform:%s" % flags.FLAGS.platform.title(), "Client Context" ] if flags.FLAGS.dest_path: dest_path = rdfvalue.RDFURN(flags.FLAGS.dest_path) else: dest_path = grr_config.CONFIG.Get( "Executables.aff4_path", context=context).Add(os.path.basename(flags.FLAGS.file)) # Now upload to the destination. maintenance_utils.UploadSignedConfigBlob(content, aff4_path=dest_path, client_context=context, token=token) print("Uploaded to %s" % dest_path) elif flags.FLAGS.subparser_name == "set_var": config = grr_config.CONFIG print("Setting %s to %s" % (flags.FLAGS.var, flags.FLAGS.val)) if flags.FLAGS.val.startswith("["): # Allow setting of basic lists. flags.FLAGS.val = flags.FLAGS.val[1:-1].split(",") config.Set(flags.FLAGS.var, flags.FLAGS.val) config.Write() elif flags.FLAGS.subparser_name == "upload_raw": if not flags.FLAGS.dest_path: flags.FLAGS.dest_path = aff4.ROOT_URN.Add("config").Add("raw") uploaded = config_updater_util.UploadRaw(flags.FLAGS.file, flags.FLAGS.dest_path, token=token) print("Uploaded to %s" % uploaded) elif flags.FLAGS.subparser_name == "upload_artifact": yaml.load(open(flags.FLAGS.file, "rb")) # Check it will parse. try: artifact.UploadArtifactYamlFile( open(flags.FLAGS.file, "rb").read(), overwrite=flags.FLAGS.overwrite_artifact) except rdf_artifacts.ArtifactDefinitionError as e: print("Error %s. You may need to set --overwrite_artifact." % e) elif flags.FLAGS.subparser_name == "delete_artifacts": artifact_list = flags.FLAGS.artifact if not artifact_list: raise ValueError("No artifact to delete given.") artifact_registry.DeleteArtifactsFromDatastore(artifact_list, token=token) print("Artifacts %s deleted." % artifact_list) elif flags.FLAGS.subparser_name == "download_missing_rekall_profiles": print("Downloading missing Rekall profiles.") s = rekall_profile_server.GRRRekallProfileServer() s.GetMissingProfiles() elif flags.FLAGS.subparser_name == "set_global_notification": notification = aff4_users.GlobalNotification( type=flags.FLAGS.type, header=flags.FLAGS.header, content=flags.FLAGS.content, link=flags.FLAGS.link) if flags.FLAGS.show_from: notification.show_from = rdfvalue.RDFDatetime( ).ParseFromHumanReadable(flags.FLAGS.show_from) if flags.FLAGS.duration: notification.duration = rdfvalue.Duration().ParseFromHumanReadable( flags.FLAGS.duration) print("Setting global notification.") print(notification) with aff4.FACTORY.Create( aff4_users.GlobalNotificationStorage.DEFAULT_PATH, aff4_type=aff4_users.GlobalNotificationStorage, mode="rw", token=token) as storage: storage.AddNotification(notification) elif flags.FLAGS.subparser_name == "rotate_server_key": print(""" You are about to rotate the server key. Note that: - Clients might experience intermittent connection problems after the server keys rotated. - It's not possible to go back to an earlier key. Clients that see a new certificate will remember the cert's serial number and refuse to accept any certificate with a smaller serial number from that point on. """) if builtins.input("Continue? [yN]: ").upper() == "Y": if flags.FLAGS.keylength: keylength = int(flags.FLAGS.keylength) else: keylength = grr_config.CONFIG["Server.rsa_key_length"] maintenance_utils.RotateServerKey(cn=flags.FLAGS.common_name, keylength=keylength)
def main(args): """Main.""" if args.subparser_name == "version": version = config_server.VERSION["packageversion"] print("GRR configuration updater {}".format(version)) return token = config_updater_util.GetToken() grr_config.CONFIG.AddContext(contexts.COMMAND_LINE_CONTEXT) grr_config.CONFIG.AddContext(contexts.CONFIG_UPDATER_CONTEXT) if args.subparser_name == "initialize": config_lib.ParseConfigCommandLine() if args.noprompt: config_updater_util.InitializeNoPrompt( grr_config.CONFIG, external_hostname=args.external_hostname, admin_password=args.admin_password, mysql_hostname=args.mysql_hostname, mysql_port=args.mysql_port, mysql_username=args.mysql_username, mysql_password=args.mysql_password, mysql_db=args.mysql_db, mysql_client_key_path=args.mysql_client_key_path, mysql_client_cert_path=args.mysql_client_cert_path, mysql_ca_cert_path=args.mysql_ca_cert_path, redownload_templates=args.redownload_templates, repack_templates=not args.norepack_templates, token=token) else: config_updater_util.Initialize( grr_config.CONFIG, external_hostname=args.external_hostname, admin_password=args.admin_password, redownload_templates=args.redownload_templates, repack_templates=not args.norepack_templates, token=token) return server_startup.Init() try: print("Using configuration %s" % grr_config.CONFIG) except AttributeError: raise RuntimeError("No valid config specified.") if args.subparser_name == "generate_keys": try: config_updater_keys_util.GenerateKeys( grr_config.CONFIG, overwrite_keys=args.overwrite_keys) except RuntimeError as e: # GenerateKeys will raise if keys exist and overwrite_keys is not set. print("ERROR: %s" % e) sys.exit(1) grr_config.CONFIG.Write() elif args.subparser_name == "repack_clients": upload = not args.noupload repacking.TemplateRepacker().RepackAllTemplates(upload=upload, token=token) elif args.subparser_name == "show_user": if args.username: print(config_updater_util.GetUserSummary(args.username)) else: print(config_updater_util.GetAllUserSummaries()) elif args.subparser_name == "update_user": config_updater_util.UpdateUser( args.username, password=args.password, is_admin=args.admin) elif args.subparser_name == "delete_user": config_updater_util.DeleteUser(args.username) elif args.subparser_name == "add_user": config_updater_util.CreateUser( args.username, password=args.password, is_admin=args.admin) elif args.subparser_name == "upload_python": config_updater_util.UploadSignedBinary( args.file, rdf_objects.SignedBinaryID.BinaryType.PYTHON_HACK, args.platform, upload_subdirectory=args.upload_subdirectory, token=token) elif args.subparser_name == "upload_exe": config_updater_util.UploadSignedBinary( args.file, rdf_objects.SignedBinaryID.BinaryType.EXECUTABLE, args.platform, upload_subdirectory=args.upload_subdirectory, token=token) elif args.subparser_name == "set_var": var = args.var val = args.val config = grr_config.CONFIG print("Setting %s to %s" % (var, val)) if val.startswith("["): # Allow setting of basic lists. val = val[1:-1].split(",") config.Set(var, val) config.Write() elif args.subparser_name == "upload_artifact": with io.open(args.file, "r") as filedesc: source = filedesc.read() try: artifact.UploadArtifactYamlFile(source, overwrite=args.overwrite_artifact) except rdf_artifacts.ArtifactDefinitionError as e: print("Error %s. You may need to set --overwrite_artifact." % e) elif args.subparser_name == "delete_artifacts": artifact_list = args.artifact if not artifact_list: raise ValueError("No artifact to delete given.") artifact_registry.DeleteArtifactsFromDatastore(artifact_list, token=token) print("Artifacts %s deleted." % artifact_list) elif args.subparser_name == "rotate_server_key": print(""" You are about to rotate the server key. Note that: - Clients might experience intermittent connection problems after the server keys rotated. - It's not possible to go back to an earlier key. Clients that see a new certificate will remember the cert's serial number and refuse to accept any certificate with a smaller serial number from that point on. """) if input("Continue? [yN]: ").upper() == "Y": if args.keylength: keylength = int(args.keylength) else: keylength = grr_config.CONFIG["Server.rsa_key_length"] maintenance_utils.RotateServerKey( cn=args.common_name, keylength=keylength)