def SetUpBinaries(self): with test_lib.FakeTime(42): code = "I am a binary file" upload_path = config_lib.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_lib.CONFIG.Get("Config.python_hack_root").Add("test") maintenance_utils.UploadSignedConfigBlob( code, aff4_path=upload_path, token=self.token) with test_lib.FakeTime(44): component = test_lib.WriteComponent( name="grr-awesome-component", build_system=rdf_client.Uname( architecture="64bit", fqdn="test.host", kernel="3.42-generic", machine="x86_64", node="test.localhost", pep425tag="Linux_debian_64bit", release="Debian", system="Linux", version="4.42"), version="1.2.3.4", raw_data="I'm a component", modules=["grr_awesome"], token=self.token) return component.summary
def RenderAjax(self, request, response): """Handle the upload via ajax.""" try: self.uploaded_file = request.FILES.items()[0][1] self.dest_path, _ = self.GetFilePath(request) content = StringIO.StringIO() for chunk in self.uploaded_file.chunks(): content.write(chunk) self.dest_path = maintenance_utils.UploadSignedConfigBlob( content.getvalue(), aff4_path=self.dest_path, token=request.token) return renderers.TemplateRenderer.Layout(self, request, response, self.success_template) except (IOError) as e: self.error = "Could not write file to database %s" % e except (IndexError) as e: self.error = "No file provided." except message.DecodeError as e: self.error = ( "Could not decode driver. This should be a signed protobuf" " generated with sign_blob") return renderers.TemplateRenderer.Layout(self, request, response, self.error_template)
def __init__(self, **kwargs): super(TestLaunchBinaries, self).__init__(**kwargs) self.context = ["Platform:%s" % self.platform.title()] self.binary = config_lib.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="GRRSignedBlob", token=self.token) except IOError: print "Uploading the test binary to the Executables area." source = os.path.join(config_lib.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 testExecuteBinariesWithArgs(self): client_mock = action_mocks.ActionMock("ExecuteBinaryCommand") code = "I am a binary file" upload_path = config_lib.CONFIG["Executables.aff4_path"].Add("test.exe") maintenance_utils.UploadSignedConfigBlob( code, aff4_path=upload_path, token=self.token) # 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="GRRUser", token=self.token) user.SetLabels("admin", owner="GRR") user.Close() with utils.Stubber(subprocess, "Popen", test_lib.Popen): for _ in test_lib.TestFlowHelper( "LaunchBinary", 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(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, test_lib.Popen.running_args[0]) # Check the binary was run with the correct command line. self.assertEqual(test_lib.Popen.running_args[1], "--value") self.assertEqual(test_lib.Popen.running_args[2], "356") # Check the command was in the tmp file. self.assertTrue(test_lib.Popen.running_args[0].startswith( config_lib.CONFIG["Client.tempdir"]))
def testExecuteLargeBinaries(self): client_mock = action_mocks.ActionMock("ExecuteBinaryCommand") code = "I am a large binary file" * 100 upload_path = config_lib.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) # There should be 24 parts to this binary. self.assertEqual(len(fd.collection), 24) # Total size is 2400. self.assertEqual(len(fd), 2400) class Popen(object): """A mock object for subprocess.Popen.""" def __init__(self, run, stdout, stderr, stdin): Popen.running_args = run Popen.stdout = stdout Popen.stderr = stderr Popen.stdin = stdin Popen.returncode = 0 # Store the content of the executable file. Popen.binary = open(run[0]).read() def communicate(self): # pylint: disable=g-bad-name return "stdout here", "stderr here" # 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="GRRUser", token=self.token) user.SetLabels("admin", owner="GRR") user.Close() with utils.Stubber(subprocess, "Popen", Popen): for _ in test_lib.TestFlowHelper( "LaunchBinary", 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(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, Popen.running_args[0]) # Check the binary was run with the correct command line. self.assertEqual(Popen.running_args[1], "--value") self.assertEqual(Popen.running_args[2], "356") # Check the command was in the tmp file. self.assertTrue(Popen.running_args[0].startswith( config_lib.CONFIG["Client.tempdir"]))
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.SetLabels("admin", owner="GRR") user.Close() with utils.Stubber(subprocess, "Popen", test_lib.Popen): for _ in test_lib.TestFlowHelper("LaunchBinary", 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(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, test_lib.Popen.running_args[0]) # Check the binary was run with the correct command line. self.assertEqual(test_lib.Popen.running_args[1], "--value") self.assertEqual(test_lib.Popen.running_args[2], "356") # Check the command was in the tmp file. self.assertTrue(test_lib.Popen.running_args[0].startswith( config.CONFIG["Client.tempdir_roots"][0]))
def testExecutePythonHackWithArgs(self): client_mock = action_mocks.ActionMock("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 test_lib.TestFlowHelper( "ExecutePythonHack", 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("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 test_lib.TestFlowHelper( "ExecutePythonHack", client_mock, client_id=self.client_id, hack_name="test", token=self.token): pass self.assertTrue(sys.test_code_ran_here)
except maintenance_utils.UserError as e: print e elif flags.FLAGS.subparser_name == "upload_python": content = open(flags.FLAGS.file, "rb").read(1024 * 1024 * 30) aff4_path = flags.FLAGS.dest_path if not aff4_path: python_hack_root_urn = config_lib.CONFIG.Get( "Config.python_hack_root") aff4_path = python_hack_root_urn.Add( os.path.basename(flags.FLAGS.file)) context = [ "Platform:%s" % flags.FLAGS.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 = config_lib.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.lib 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
password = getpass.getpass(prompt="Please enter password for user '%s': " % flags.FLAGS.username) labels = [] if not flags.FLAGS.noadmin: labels.append("admin") UpdateUser(flags.FLAGS.username, password, labels) elif flags.FLAGS.subparser_name == "upload_python": content = open(flags.FLAGS.file).read(1024*1024*30) aff4_path = flags.FLAGS.dest_path if not aff4_path: python_hack_root_urn = config_lib.CONFIG.Get("Config.python_hack_root") aff4_path = python_hack_root_urn.Add(os.path.basename(flags.FLAGS.file)) context = ["Platform:%s" % flags.FLAGS.platform.title(), "Client"] maintenance_utils.UploadSignedConfigBlob(content, aff4_path=aff4_path, client_context=context) elif flags.FLAGS.subparser_name == "upload_exe": content = open(flags.FLAGS.file).read(1024*1024*30) context = ["Platform:%s" % flags.FLAGS.platform.title(), "Client"] if flags.FLAGS.dest_path: dest_path = rdfvalue.RDFURN(flags.FLAGS.dest_path) else: dest_path = config_lib.CONFIG.Get( "Executables.aff4_path", context=context).Add( os.path.basename(flags.FLAGS.file)) # Now upload to the destination. uploaded = maintenance_utils.UploadSignedConfigBlob(