def __init__(self, **kwargs): super(TestLaunchBinaries, self).__init__(**kwargs) self.context = ["Platform:%s" % self.platform.title()] self.binary = config.CONFIG.Get( "Executables.aff4_path", context=self.context).Add("test/%s" % self.ds_names[self.platform]) self.args = dict(binary=self.binary) try: aff4.FACTORY.Open(self.binary, aff4_type=aff4_collects.GRRSignedBlob, token=self.token) except IOError: print "Uploading the test binary to the Executables area." source = os.path.join(config.CONFIG["Test.data_dir"], self.filenames[self.platform]) if not os.path.exists(source): self.fail("Path %s should exist." % source) maintenance_utils.UploadSignedConfigBlob( open(source, "rb").read(), aff4_path=self.binary, client_context=self.context, token=self.token, limit=self.limit)
def SetUpBinaries(self): with test_lib.FakeTime(42): code = "I am a binary file" upload_path = config.CONFIG.Get("Config.aff4_root").Add( "executables/windows/test.exe") maintenance_utils.UploadSignedConfigBlob(code, aff4_path=upload_path, token=self.token) with test_lib.FakeTime(43): code = "I'm a python hack" upload_path = config.CONFIG.Get("Config.python_hack_root").Add( "test") maintenance_utils.UploadSignedConfigBlob(code, aff4_path=upload_path, token=self.token)
def testExecuteLargeBinaries(self): client_mock = action_mocks.ActionMock(standard.ExecuteBinaryCommand) code = "I am a large binary file" * 100 upload_path = config.CONFIG["Executables.aff4_path"].Add("test.exe") maintenance_utils.UploadSignedConfigBlob(code, aff4_path=upload_path, limit=100, token=self.token) # Ensure the aff4 collection has many items. fd = aff4.FACTORY.Open(upload_path, token=self.token) # Total size is 2400. self.assertEqual(len(fd), 2400) # There should be 24 parts to this binary. self.assertEqual(len(fd.collection), 24) # This flow has an acl, the user needs to be admin. user = aff4.FACTORY.Create("aff4:/users/%s" % self.token.username, mode="rw", aff4_type=users.GRRUser, token=self.token) user.SetLabel("admin", owner="GRRTest") user.Close() with utils.Stubber(subprocess, "Popen", client_test_lib.Popen): for _ in flow_test_lib.TestFlowHelper( administrative.LaunchBinary.__name__, client_mock, client_id=self.client_id, binary=upload_path, command_line="--value 356", token=self.token): pass # Check that the executable file contains the code string. self.assertEqual(client_test_lib.Popen.binary, code) # At this point, the actual binary should have been cleaned up by the # client action so it should not exist. self.assertRaises(IOError, open, client_test_lib.Popen.running_args[0]) # Check the binary was run with the correct command line. self.assertEqual(client_test_lib.Popen.running_args[1], "--value") self.assertEqual(client_test_lib.Popen.running_args[2], "356") # Check the command was in the tmp file. self.assertTrue(client_test_lib.Popen.running_args[0].startswith( config.CONFIG["Client.tempdir_roots"][0]))
def testExecutePythonHackWithArgs(self): client_mock = action_mocks.ActionMock(standard.ExecutePython) sys.test_code_ran_here = 1234 code = """ import sys sys.test_code_ran_here = py_args['value'] """ maintenance_utils.UploadSignedConfigBlob( code, aff4_path="aff4:/config/python_hacks/test", token=self.token) for _ in flow_test_lib.TestFlowHelper( administrative.ExecutePythonHack.__name__, client_mock, client_id=self.client_id, hack_name="test", py_args=dict(value=5678), token=self.token): pass self.assertEqual(sys.test_code_ran_here, 5678)
def testExecutePythonHack(self): client_mock = action_mocks.ActionMock(standard.ExecutePython) # This is the code we test. If this runs on the client mock we can check for # this attribute. sys.test_code_ran_here = False code = """ import sys sys.test_code_ran_here = True """ maintenance_utils.UploadSignedConfigBlob( code, aff4_path="aff4:/config/python_hacks/test", token=self.token) for _ in flow_test_lib.TestFlowHelper( administrative.ExecutePythonHack.__name__, client_mock, client_id=self.client_id, hack_name="test", token=self.token): pass self.assertTrue(sys.test_code_ran_here)
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))
def RepackTemplate(self, template_path, output_dir, upload=False, token=None, sign=False, context=None, signed_template=False): """Repack binaries based on the configuration. We repack all templates in the templates directory. We expect to find only functioning templates, all other files should be removed. Each template contains a build.yaml that specifies how it was built and how it should be repacked. Args: template_path: template path string output_dir: Output files will be put in this directory. upload: If specified we also upload the repacked binary into the token: Token to use when uploading to the datastore. sign: If true, we want to digitally sign the installer. context: Array of context strings signed_template: If true, the libraries in the template are already signed. This is only used for windows when repacking the template multiple times. Returns: A list of output installers generated. """ orig_config = config.CONFIG repack_config = RepackConfig() print "Repacking template: %s" % template_path config.CONFIG = repack_config.GetConfigFromTemplate(template_path) result_path = None try: repack_context = config.CONFIG["Template.build_context"] if context: repack_context.extend(context) output_path = os.path.join( output_dir, config.CONFIG.Get("ClientRepacker.output_filename", context=repack_context)) print "Using context: %s and labels: %s" % ( repack_context, config.CONFIG.Get("Client.labels", context=repack_context)) try: signer = None if sign: signer = self.GetSigner(repack_context) builder_obj = self.GetRepacker(context=repack_context, signer=signer) builder_obj.signed_template = signed_template result_path = builder_obj.MakeDeployableBinary( template_path, output_path) except Exception as e: # pylint: disable=broad-except print "Repacking template %s failed: %s" % (template_path, e) if result_path: print "Repacked into %s" % result_path if upload: # We delay import here so we don't have to import the entire server # codebase and do full server init if we're just building and # repacking clients. This codepath is used by config_updater # initialize # pylint: disable=g-import-not-at-top from grr.server import maintenance_utils # pylint: enable=g-import-not-at-top dest = config.CONFIG.Get("Executables.installer", context=repack_context) maintenance_utils.UploadSignedConfigBlob( open(result_path, "rb").read(100 * 1024 * 1024), dest, client_context=repack_context, token=token) else: print "Failed to repack %s." % template_path finally: config.CONFIG = orig_config return result_path