def testGenClientConfig_ignoreBuilderContext(self): with test_lib.PreserveConfig(): # Define a secondary config with special values for the ClientBuilder # context. str_override = """ Test Context: Client.labels: [label0, label1] ClientBuilder Context: Client.labels: [build-label0, build-label1] """ override = config_lib.YamlParser(data=str_override).RawData() config.CONFIG.MergeData(override) # Sanity-check that the secondary config was merged into the global # config. self.assertEqual(config.CONFIG["Client.labels"], ["label0", "label1"]) repacker = build.ClientRepacker() context = [ "Test Context", "ClientBuilder Context", "Client Context" ] str_client_config = repacker.GetClientConfig(context) client_config = config_lib.YamlParser( data=str_client_config).RawData() # Settings particular to the ClientBuilder context should not carry over # into the generated client config. self.assertEqual(client_config["Client.labels"], ["label0", "label1"])
def testGenClientConfig(self): with test_lib.ConfigOverrider({"Client.build_environment": "test_env"}): deployer = build.ClientRepacker() data = deployer.GetClientConfig(["Client Context"], validate=True) parser = config_lib.YamlParser(data=data) raw_data = parser.RawData() self.assertIn("Client.deploy_time", raw_data)
def testRepackerDummyClientConfig(self): """Ensure our dummy client config can pass validation. This config is used to exercise repacking code in integration testing, here we just make sure it will pass validation. """ new_config = config.CONFIG.MakeNewConfig() new_config.Initialize() new_config.LoadSecondaryConfig( os.path.join(config.CONFIG["Test.data_dir"], "dummyconfig.yaml")) build.ClientRepacker().ValidateEndConfig(new_config)
def testRepackAll(self): """Test repacking all binaries.""" self.executables_dir = config_lib.Resource().Filter("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() packaged_config.Initialize(parser=config_lib.YamlParser, data=yaml.safe_dump(loaded)) packaged_config.Validate( sections=build.ClientRepacker.CONFIG_SECTIONS) repacker = build.ClientRepacker() repacker.ValidateEndConfig(packaged_config)
def WriteClientConfig(self): repacker = build.ClientRepacker(context=self.context) repacker.context = self.context # Generate a config file. with open( os.path.join( self.target_binary_dir, config_lib.CONFIG.Get("ClientBuilder.config_filename", context=self.context)), "wb") as fd: fd.write( repacker.GetClientConfig(["Client Context"] + self.context, validate=False))
def GetClientConfig(filename): """Write client config to filename.""" config_lib.SetPlatformArchContext() config_lib.ParseConfigCommandLine() context = list(grr_config.CONFIG.context) context.append("Client Context") deployer = build.ClientRepacker() # Disable timestamping so we can get a reproducible and cachable config file. config_data = deployer.GetClientConfig( context, validate=True, deploy_timestamp=False) builder = build.ClientBuilder() with open(filename, "w") as fd: fd.write(config_data) builder.WriteBuildYaml(fd, build_timestamp=False)
def BuildInstallerPkg(self, output_file): """Builds a package (.pkg) using PackageMaker.""" build_files_dir = config_lib.Resource().Filter( "install_data/macosx/client") pmdoc_dir = os.path.join(build_files_dir, "grr.pmdoc") client_name = config_lib.CONFIG.Get("Client.name", context=self.context) plist_name = config_lib.CONFIG.Get("Client.plist_filename", context=self.context) out_build_files_dir = build_files_dir.replace( config_lib.Resource().Filter("grr"), self.build_dir) out_pmdoc_dir = os.path.join(self.build_dir, "%s.pmdoc" % client_name) utils.EnsureDirExists(out_build_files_dir) utils.EnsureDirExists(out_pmdoc_dir) utils.EnsureDirExists( config_lib.CONFIG.Get("ClientBuilder.package_dir", context=self.context)) self.GenerateFile(input_filename=os.path.join(build_files_dir, "grr.plist.in"), output_filename=os.path.join(self.build_dir, plist_name)) self.GenerateFile(input_filename=os.path.join(pmdoc_dir, "index.xml.in"), output_filename=os.path.join(out_pmdoc_dir, "index.xml")) self.GenerateFile(input_filename=os.path.join(pmdoc_dir, "01grr.xml.in"), output_filename=os.path.join( out_pmdoc_dir, "01%s.xml" % client_name)) self.GenerateFile(input_filename=os.path.join(pmdoc_dir, "01grr-contents.xml"), output_filename=os.path.join( out_pmdoc_dir, "01%s-contents.xml" % client_name)) self.GenerateFile(input_filename=os.path.join(pmdoc_dir, "02com.xml.in"), output_filename=os.path.join(out_pmdoc_dir, "02com.xml")) self.GenerateFile(input_filename=os.path.join(pmdoc_dir, "02com-contents.xml"), output_filename=os.path.join(out_pmdoc_dir, "02com-contents.xml")) self.GenerateFile(input_filename=os.path.join(build_files_dir, "preinstall.sh.in"), output_filename=os.path.join(self.build_dir, "preinstall.sh")) self.GenerateFile(input_filename=os.path.join(build_files_dir, "postinstall.sh.in"), output_filename=os.path.join(self.build_dir, "postinstall.sh")) output_basename = config_lib.CONFIG.Get( "ClientBuilder.output_basename", context=self.context) # Rename the generated binaries to the correct name. template_binary_dir = os.path.join( config_lib.CONFIG.Get("PyInstaller.distpath", context=self.context), "grr-client") target_binary_dir = os.path.join(self.build_dir, "%s" % output_basename) if template_binary_dir != 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_lib.CONFIG.Get("Client.binary_name", context=self.context))) repacker = build.ClientRepacker(context=self.context) repacker.context = self.context # Generate a config file. with open( os.path.join( target_binary_dir, config_lib.CONFIG.Get("ClientBuilder.config_filename", context=self.context)), "wb") as fd: fd.write( repacker.GetClientConfig(["Client Context"] + self.context, validate=False)) print "Fixing file ownership and permissions" command = [ "sudo", "/usr/sbin/chown", "-R", "root:wheel", self.build_dir ] # Change the owner, group and permissions of the binaries print "Running: %s" % " ".join(command) subprocess.call(command) command = ["sudo", "/bin/chmod", "-R", "755", self.build_dir] print "Running: %s" % " ".join(command) subprocess.call(command) print "Building a package with PackageMaker" pkg = "%s-%s.pkg" % (config_lib.CONFIG.Get("Client.name", context=self.context), config_lib.CONFIG.Get("Source.version_string", context=self.context)) output_pkg_path = os.path.join(self.pkg_dir, pkg) command = [ config_lib.CONFIG.Get("ClientBuilder.package_maker_path", context=self.context), "--doc", out_pmdoc_dir, "--out", output_pkg_path ] print "Running: %s " % " ".join(command) ret = subprocess.call(command) if ret != 0: msg = "PackageMaker returned an error (%d)." % ret print msg raise RuntimeError(msg) print "Copying output to templates location: %s -> %s" % ( output_pkg_path, output_file) utils.EnsureDirExists(os.path.dirname(output_file)) shutil.copyfile(output_pkg_path, output_file) # Change the owner, group and permissions of the binaries back. command = [ "sudo", "/usr/sbin/chown", "-R", "%s:staff" % getpass.getuser(), self.build_dir ] print "Running: %s" % " ".join(command) subprocess.call(command)