def _ValidateFleetspeakServiceConfig(self, config_path): """Validates a Fleetspeak service config. Checks that the given file is a valid TextFormat representation of a Fleetspeak service config proto. Args: config_path: Path to the config file. Raises: BuildError: If the config is not valid. """ with open(config_path, "rb") as f: parsed_config = text_format.Parse( f.read(), fs_system_pb2.ClientServiceConfig(), descriptor_pool=fs_config_pb2.DESCRIPTOR.pool) if parsed_config.factory != "Daemon": raise build.BuildError( "Fleetspeak config does not have the expected factory type." ) daemon_cfg = fs_config_pb2.Config() parsed_config.config.Unpack(daemon_cfg) if not daemon_cfg.argv: raise build.BuildError( "Fleetspeak daemon service config does not specify command line " "args.")
def MakeDeployableBinary(self, template_path, output_path): """This will add the config to the client template and create a .rpm.""" rpmbuild_binary = "/usr/bin/rpmbuild" if not os.path.exists(rpmbuild_binary): logging.error("rpmbuild not found, unable to repack client.") return None with utils.TempDirectory() as tmp_dir: template_dir = os.path.join(tmp_dir, "dist") utils.EnsureDirExists(template_dir) zf = zipfile.ZipFile(template_path) for name in zf.namelist(): dirname = os.path.dirname(name) utils.EnsureDirExists(os.path.join(template_dir, dirname)) with io.open(os.path.join(template_dir, name), "wb") as fd: fd.write(zf.read(name)) self._ProcessUniversalTemplate(template_dir) # Set up a RPM building environment. rpm_root_dir = os.path.join(tmp_dir, "rpmbuild") rpm_build_dir = os.path.join(rpm_root_dir, "BUILD") utils.EnsureDirExists(rpm_build_dir) rpm_buildroot_dir = os.path.join(rpm_root_dir, "BUILDROOT") utils.EnsureDirExists(rpm_buildroot_dir) rpm_rpms_dir = os.path.join(rpm_root_dir, "RPMS") utils.EnsureDirExists(rpm_rpms_dir) rpm_specs_dir = os.path.join(rpm_root_dir, "SPECS") utils.EnsureDirExists(rpm_specs_dir) template_binary_dir = os.path.join(tmp_dir, "dist/rpmbuild/grr-client") target_binary_dir = "%s%s" % (rpm_build_dir, config.CONFIG.Get( "ClientBuilder.target_dir", context=self.context)) utils.EnsureDirExists(os.path.dirname(target_binary_dir)) try: shutil.rmtree(target_binary_dir) except OSError: pass # TODO(user):pytype: incorrect move() definition in typeshed. # pytype: disable=wrong-arg-types shutil.move(template_binary_dir, target_binary_dir) # pytype: enable=wrong-arg-types client_name = config.CONFIG.Get("Client.name", context=self.context) client_binary_name = config.CONFIG.Get("Client.binary_name", context=self.context) if client_binary_name != "grr-client": # TODO(user):pytype: incorrect move() definition in typeshed. # pytype: disable=wrong-arg-types shutil.move( os.path.join(target_binary_dir, "grr-client"), os.path.join(target_binary_dir, client_binary_name)) # pytype: enable=wrong-arg-types if config.CONFIG.Get("Client.fleetspeak_enabled", context=self.context): self._GenerateFleetspeakConfig(template_dir, rpm_build_dir) if not config.CONFIG.Get("Client.fleetspeak_service_name", context=self.context): # The Fleetspeak service name is required when generating the RPM # spec file. raise build.BuildError( "Client.fleetspeak_service_name is not set.") if config.CONFIG.Get("ClientBuilder.fleetspeak_bundled", context=self.context): self._GenerateBundledFleetspeakFiles( os.path.join(template_dir, "bundled-fleetspeak"), rpm_build_dir) shutil.copy( config.CONFIG.Get( "ClientBuilder.fleetspeak_client_config", context=self.context), os.path.join(rpm_build_dir, "etc/fleetspeak-client/client.config")) else: self._GenerateInitConfigs(template_dir, rpm_build_dir) # Generate spec spec_filename = os.path.join(rpm_specs_dir, "%s.spec" % client_name) build_helpers.GenerateFile(os.path.join( tmp_dir, "dist/rpmbuild/grr.spec.in"), spec_filename, context=self.context) # Generate prelinking blacklist file prelink_target_filename = os.path.join(rpm_build_dir, "etc/prelink.conf.d", "%s.conf" % client_name) utils.EnsureDirExists(os.path.dirname(prelink_target_filename)) build_helpers.GenerateFile(os.path.join( tmp_dir, "dist/rpmbuild/prelink_blacklist.conf.in"), prelink_target_filename, context=self.context) # Create a client config. client_context = ["Client Context"] + self.context client_config_content = build_helpers.GetClientConfig( client_context) with io.open(os.path.join( target_binary_dir, config.CONFIG.Get("ClientBuilder.config_filename", context=self.context)), "w", encoding="utf-8") as fd: fd.write(client_config_content) # Set the daemon to executable. os.chmod(os.path.join(target_binary_dir, client_binary_name), 0o755) client_arch = config.CONFIG.Get("Template.arch", context=self.context) if client_arch == "amd64": client_arch = "x86_64" # Create wrapper script if os.path.exists(os.path.join(target_binary_dir, "wrapper.sh.in")): build_helpers.GenerateFile( os.path.join(target_binary_dir, "wrapper.sh.in"), os.path.join(target_binary_dir, "wrapper.sh"), context=self.context) os.chmod(os.path.join(target_binary_dir, "wrapper.sh"), 0o755) command = [ rpmbuild_binary, "--define", "_topdir " + rpm_root_dir, "--target", client_arch, "--buildroot", rpm_buildroot_dir, "-bb", spec_filename ] try: subprocess.check_output(command, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: logging.error("Error calling %s.", command) logging.error(e.output) raise client_version = config.CONFIG.Get("Template.version_string", context=self.context) rpm_filename = os.path.join( rpm_rpms_dir, client_arch, "%s-%s-1.%s.rpm" % (client_name, client_version, client_arch)) utils.EnsureDirExists(os.path.dirname(output_path)) shutil.move(rpm_filename, output_path) logging.info("Created package %s", output_path) self._Sign(output_path) return output_path
def _GenerateDPKGFiles(self, template_path): """Generates the files needed by dpkg-buildpackage.""" fleetspeak_enabled = config.CONFIG.Get("Client.fleetspeak_enabled", context=self.context) fleetspeak_bundled = config.CONFIG.Get( "ClientBuilder.fleetspeak_bundled", context=self.context) if fleetspeak_bundled and not fleetspeak_enabled: raise build.BuildError("ClientBuilder.fleetspeak_bundled requires " "Client.fleetspeak_enabled to be set.") # Rename the generated binaries to the correct name. template_binary_dir = os.path.join(template_path, "dist/debian/grr-client") package_name = config.CONFIG.Get("ClientBuilder.package_name", context=self.context) target_binary_dir = os.path.join( template_path, "dist/debian/%s%s" % (package_name, config.CONFIG.Get("ClientBuilder.target_dir", context=self.context))) if package_name == "grr-client": # Need to rename the template path or the move will fail. shutil.move(template_binary_dir, "%s-template" % template_binary_dir) template_binary_dir = "%s-template" % template_binary_dir utils.EnsureDirExists(os.path.dirname(target_binary_dir)) shutil.move(template_binary_dir, target_binary_dir) shutil.move( os.path.join(target_binary_dir, "grr-client"), os.path.join( target_binary_dir, config.CONFIG.Get("Client.binary_name", context=self.context))) deb_in_dir = os.path.join(template_path, "dist/debian/debian.in/") if not os.path.isdir(deb_in_dir): # This is an universal (fleetspeak + legacy) template. # In prior versions, debian.in used to contain different files for a # fleetspeak-enabled and legacy template respectively. if fleetspeak_enabled: deb_in_dir = os.path.join(template_path, "dist/debian/fleetspeak-debian.in/") else: deb_in_dir = os.path.join(template_path, "dist/debian/legacy-debian.in/") build_helpers.GenerateDirectory(deb_in_dir, os.path.join(template_path, "dist/debian"), [("grr-client", package_name)], context=self.context) # Generate directories for the /usr/sbin link. utils.EnsureDirExists( os.path.join(template_path, "dist/debian/%s/usr/sbin" % package_name)) if os.path.exists(os.path.join(target_binary_dir, "wrapper.sh.in")): build_helpers.GenerateFile(os.path.join(target_binary_dir, "wrapper.sh.in"), os.path.join(target_binary_dir, "wrapper.sh"), context=self.context) os.chmod(os.path.join(target_binary_dir, "wrapper.sh"), 0o755) if fleetspeak_enabled: if fleetspeak_bundled: self._GenerateFleetspeakConfig( template_path, "/etc/fleetspeak-client/textservices") self._GenerateBundledFleetspeakFiles( os.path.join(template_path, "dist/bundled-fleetspeak"), os.path.join(template_path, "dist/debian", package_name)) shutil.copy( config.CONFIG.Get("ClientBuilder.fleetspeak_client_config", context=self.context), os.path.join(template_path, "dist", "debian", package_name, "etc/fleetspeak-client/client.config")) else: fleetspeak_service_dir = config.CONFIG.Get( "ClientBuilder.fleetspeak_service_dir", context=self.context) self._GenerateFleetspeakConfig(template_path, fleetspeak_service_dir) else: # Generate the nanny template. # This exists from client version 3.1.2.5 onwards. build_helpers.GenerateFile(os.path.join(target_binary_dir, "nanny.sh.in"), os.path.join(target_binary_dir, "nanny.sh"), context=self.context) # Generate the upstart template. build_helpers.GenerateFile( os.path.join(template_path, "dist/debian/upstart.in/grr-client.conf"), os.path.join(template_path, "dist/debian/%s.upstart" % package_name), context=self.context) # Generate the initd template. The init will not run if it detects upstart # is present. build_helpers.GenerateFile( os.path.join(template_path, "dist/debian/initd.in/grr-client"), os.path.join(template_path, "dist/debian/%s.init" % package_name), context=self.context) # Generate the systemd unit file. build_helpers.GenerateFile( os.path.join(template_path, "dist/debian/systemd.in/grr-client.service"), os.path.join(template_path, "dist/debian/%s.service" % package_name), context=self.context) # Clean up the template dirs. # Some of the dirs might be missing in older template versions, so removing # conditionally. self._RmTreeIfExists( os.path.join(template_path, "dist/debian/debian.in")) self._RmTreeIfExists( os.path.join(template_path, "dist/debian/fleetspeak-debian.in")) self._RmTreeIfExists( os.path.join(template_path, "dist/debian/legacy-debian.in")) self._RmTreeIfExists( os.path.join(template_path, "dist/debian/upstart.in")) self._RmTreeIfExists( os.path.join(template_path, "dist/debian/initd.in")) self._RmTreeIfExists( os.path.join(template_path, "dist/debian/systemd.in")) self._RmTreeIfExists(os.path.join(template_path, "dist/fleetspeak")) self._RmTreeIfExists( os.path.join(template_path, "dist/bundled-fleetspeak"))