コード例 #1
0
    def testNewArtifactLoaded(self):
        """Simulate a new artifact being loaded into the store via the UI."""
        cmd_artifact = """name: "TestCmdArtifact"
doc: "Test command artifact for dpkg."
sources:
- type: "COMMAND"
  attributes:
    cmd: "/usr/bin/dpkg"
    args: ["--list"]
labels: [ "Software" ]
supported_os: [ "Linux" ]
"""
        no_datastore_artifact = """name: "NotInDatastore"
doc: "Test command artifact for dpkg."
sources:
- type: "COMMAND"
  attributes:
    cmd: "/usr/bin/dpkg"
    args: ["--list"]
labels: [ "Software" ]
supported_os: [ "Linux" ]
"""
        test_registry = artifact_registry.ArtifactRegistry()
        test_registry.ClearRegistry()
        test_registry.AddDatastoreSource(
            rdfvalue.RDFURN("aff4:/artifact_store"))
        test_registry._dirty = False
        with utils.Stubber(artifact_registry, "REGISTRY", test_registry):
            with self.assertRaises(rdf_artifacts.ArtifactNotRegisteredError):
                artifact_registry.REGISTRY.GetArtifact("TestCmdArtifact")

            with self.assertRaises(rdf_artifacts.ArtifactNotRegisteredError):
                artifact_registry.REGISTRY.GetArtifact("NotInDatastore")

            # Add artifact to datastore but not registry
            artifact_coll = artifact_registry.ArtifactCollection(
                rdfvalue.RDFURN("aff4:/artifact_store"))
            with data_store.DB.GetMutationPool() as pool:
                for artifact_val in artifact_registry.REGISTRY.ArtifactsFromYaml(
                        cmd_artifact):
                    artifact_coll.Add(artifact_val, mutation_pool=pool)

            # Add artifact to registry but not datastore
            for artifact_val in artifact_registry.REGISTRY.ArtifactsFromYaml(
                    no_datastore_artifact):
                artifact_registry.REGISTRY.RegisterArtifact(
                    artifact_val,
                    source="datastore",
                    overwrite_if_exists=False)

            # This should succeeded because the artifacts will be reloaded from the
            # datastore.
            self.assertTrue(
                artifact_registry.REGISTRY.GetArtifact("TestCmdArtifact"))

            # We registered this artifact with datastore source but didn't
            # write it into aff4. This simulates an artifact that was
            # uploaded in the UI then later deleted. We expect it to get
            # cleared when the artifacts are reloaded from the datastore.
            with self.assertRaises(rdf_artifacts.ArtifactNotRegisteredError):
                artifact_registry.REGISTRY.GetArtifact("NotInDatastore")
コード例 #2
0
 def testCheckPermissionsReturnsTrueIfGroupWasAuthorized(self):
   self.auth_manager.DenyAll("subject-bar")
   with utils.Stubber(self.group_access_manager, "MemberOfAuthorizedGroup",
                      lambda *args: True):
     self.assertTrue(
         self.auth_manager.CheckPermissions("user-bar", "subject-bar"))
コード例 #3
0
ファイル: administrative_test.py プロジェクト: qsdj/grr
    def testStartupHandler(self):
        client_id = test_lib.TEST_CLIENT_ID
        rel_client_id = client_id.Basename()
        data_store.REL_DB.WriteClientMetadata(rel_client_id,
                                              fleetspeak_enabled=True)

        self._RunSendStartupInfo(client_id)

        # AFF4 client.

        # Check the client's boot time and info.
        fd = aff4.FACTORY.Open(client_id, token=self.token)
        client_info = fd.Get(fd.Schema.CLIENT_INFO)
        boot_time = fd.Get(fd.Schema.LAST_BOOT_TIME)

        self.assertEqual(client_info.client_name, config.CONFIG["Client.name"])
        self.assertEqual(client_info.client_description,
                         config.CONFIG["Client.description"])

        # Check that the boot time is accurate.
        self.assertAlmostEqual(psutil.boot_time(),
                               boot_time.AsSecondsSinceEpoch())

        # objects.ClientSnapshot.

        si = data_store.REL_DB.ReadClientStartupInfo(rel_client_id)
        self.assertIsNotNone(si)
        self.assertEqual(si.client_info.client_name,
                         config.CONFIG["Client.name"])
        self.assertEqual(si.client_info.client_description,
                         config.CONFIG["Client.description"])

        # Run it again - this should not update any record.
        self._RunSendStartupInfo(client_id)

        # AFF4 client.
        fd = aff4.FACTORY.Open(client_id, token=self.token)
        self.assertEqual(boot_time.age, fd.Get(fd.Schema.LAST_BOOT_TIME).age)
        self.assertEqual(client_info.age, fd.Get(fd.Schema.CLIENT_INFO).age)

        # objects.ClientSnapshot.

        new_si = data_store.REL_DB.ReadClientStartupInfo(rel_client_id)
        self.assertEqual(new_si, si)

        # Simulate a reboot.
        current_boot_time = psutil.boot_time()
        with utils.Stubber(psutil, "boot_time",
                           lambda: current_boot_time + 600):

            # Run it again - this should now update the boot time.
            self._RunSendStartupInfo(client_id)

            # AFF4 client.

            # Ensure only this attribute is updated.
            fd = aff4.FACTORY.Open(client_id, token=self.token)
            self.assertNotEqual(int(boot_time.age),
                                int(fd.Get(fd.Schema.LAST_BOOT_TIME).age))
            self.assertEqual(int(client_info.age),
                             int(fd.Get(fd.Schema.CLIENT_INFO).age))

            # objects.ClientSnapshot.
            new_si = data_store.REL_DB.ReadClientStartupInfo(rel_client_id)
            self.assertIsNotNone(new_si)
            self.assertNotEqual(new_si.boot_time, si.boot_time)

            # Now set a new client build time.
            with test_lib.ConfigOverrider({"Client.build_time": time.ctime()}):

                # Run it again - this should now update the client info.
                self._RunSendStartupInfo(client_id)

                # AFF4 client.

                # Ensure the client info attribute is updated.
                fd = aff4.FACTORY.Open(client_id, token=self.token)
                self.assertNotEqual(int(client_info.age),
                                    int(fd.Get(fd.Schema.CLIENT_INFO).age))

                # objects.ClientSnapshot.
                new_si = data_store.REL_DB.ReadClientStartupInfo(rel_client_id)
                self.assertIsNotNone(new_si)
                self.assertNotEqual(new_si.client_info, si.client_info)
コード例 #4
0
    def testBlockingTasks(self):
        # The pool starts off with the minimum number of threads.
        self.assertEqual(len(self.test_pool), self.NUMBER_OF_THREADS)

        done_event = threading.Event()
        self.lock = threading.Lock()
        res = []

        def Block(done):
            done.wait()

        def Insert(list_obj, element):
            with self.lock:
                list_obj.append(element)

        # Ensure that the thread pool is able to add the correct number of threads
        # deterministically.
        with utils.Stubber(self.test_pool, "CPUUsage", lambda: 0):
            # Schedule the maximum number of threads of blocking tasks and the same of
            # insert tasks. The threads are now all blocked, and the inserts are
            # waiting in the queue.
            for _ in range(self.MAXIMUM_THREADS):
                self.test_pool.AddTask(Block, (done_event, ), "Blocking")

            # Wait until the threadpool picks up the task.
            self.WaitUntil(
                lambda: self.test_pool.busy_threads == self.NUMBER_OF_THREADS)

            # Now there are minimum number of threads active and the rest are sitting
            # on the queue.
            self.assertEqual(self.test_pool.pending_tasks,
                             self.MAXIMUM_THREADS - self.NUMBER_OF_THREADS)

            # Now as we push these tasks on the queue, new threads will be created and
            # they will receive the blocking tasks from the queue.
            for i in range(self.MAXIMUM_THREADS):
                self.test_pool.AddTask(Insert, (res, i),
                                       "Insert",
                                       blocking=True,
                                       inline=False)

            # There should be 20 workers created and they should consume all the
            # blocking tasks.
            self.WaitUntil(
                lambda: self.test_pool.busy_threads == self.MAXIMUM_THREADS)

            # No Insert tasks are running yet.
            self.assertEqual(res, [])

            # There are 20 tasks waiting on the queue.
            self.assertEqual(self.test_pool.pending_tasks,
                             self.MAXIMUM_THREADS)

            # Inserting more tasks than the queue can hold should lead to processing
            # the tasks inline. This effectively causes these tasks to skip over the
            # tasks which are waiting in the queue.
            for i in range(10, 20):
                self.test_pool.AddTask(Insert, (res, i), "Insert", inline=True)

            res.sort()
            self.assertEqual(res, range(10, 20))

            # This should release all the busy tasks. It will also cause the workers
            # to process all the Insert tasks in the queue.
            done_event.set()

            self.test_pool.Join()

            # Now the rest of the tasks should have been processed as well.
            self.assertEqual(sorted(res[10:]), range(20))
コード例 #5
0
ファイル: worker_test.py プロジェクト: rainser/grr
    def testNoValidStatusRaceIsResolved(self):

        # This tests for the regression of a long standing race condition we saw
        # where notifications would trigger the reading of another request that
        # arrives later but wasn't completely written to the database yet.
        # Timestamp based notification handling should eliminate this bug.

        # We need a random flow object for this test.
        session_id = flow.StartFlow(client_id=self.client_id,
                                    flow_name="WorkerSendingTestFlow",
                                    token=self.token)
        worker_obj = worker_lib.GRRWorker(token=self.token)
        manager = queue_manager.QueueManager(token=self.token)

        manager.DeleteNotification(session_id)
        manager.Flush()

        # We have a first request that is complete (request_id 1, response_id 1).
        self.SendResponse(session_id, "Response 1")

        # However, we also have request #2 already coming in. The race is that
        # the queue manager might write the status notification to
        # session_id/state as "status:00000002" but not the status response
        # itself yet under session_id/state/request:00000002

        request_id = 2
        response_id = 1
        flow_manager = queue_manager.QueueManager(token=self.token)
        flow_manager.FreezeTimestamp()

        flow_manager.QueueResponse(
            rdf_flows.GrrMessage(
                source=self.client_id,
                session_id=session_id,
                payload=rdf_protodict.DataBlob(string="Response 2"),
                request_id=request_id,
                auth_state="AUTHENTICATED",
                response_id=response_id))

        status = rdf_flows.GrrMessage(
            source=self.client_id,
            session_id=session_id,
            payload=rdf_flows.GrrStatus(
                status=rdf_flows.GrrStatus.ReturnedStatus.OK),
            request_id=request_id,
            response_id=response_id + 1,
            auth_state="AUTHENTICATED",
            type=rdf_flows.GrrMessage.Type.STATUS)

        # Now we write half the status information.
        data_store.DB.StoreRequestsAndResponses(new_responses=[(status, None)])

        # We make the race even a bit harder by saying the new notification gets
        # written right before the old one gets deleted. If we are not careful here,
        # we delete the new notification as well and the flow becomes stuck.

        # pylint: disable=invalid-name
        def WriteNotification(self, arg_session_id, start=None, end=None):
            if arg_session_id == session_id:
                flow_manager.QueueNotification(session_id=arg_session_id)
                flow_manager.Flush()

            self.DeleteNotification.old_target(self,
                                               arg_session_id,
                                               start=start,
                                               end=end)

        # pylint: enable=invalid-name

        with utils.Stubber(queue_manager.QueueManager, "DeleteNotification",
                           WriteNotification):
            # This should process request 1 but not touch request 2.
            worker_obj.RunOnce()
            worker_obj.thread_pool.Join()

        flow_obj = aff4.FACTORY.Open(session_id, token=self.token)
        self.assertFalse(flow_obj.context.backtrace)
        self.assertNotEqual(flow_obj.context.state,
                            rdf_flow_runner.FlowContext.State.ERROR)

        request_data = data_store.DB.ReadResponsesForRequestId(session_id, 2)
        request_data.sort(key=lambda msg: msg.response_id)
        self.assertEqual(len(request_data), 2)

        # Make sure the status and the original request are still there.
        self.assertEqual(request_data[0].args_rdf_name, "DataBlob")
        self.assertEqual(request_data[1].args_rdf_name, "GrrStatus")

        # But there is nothing for request 1.
        request_data = data_store.DB.ReadResponsesForRequestId(session_id, 1)
        self.assertEqual(request_data, [])

        # The notification for request 2 should have survived.
        with queue_manager.QueueManager(token=self.token) as manager:
            notifications = manager.GetNotifications(queues.FLOWS)
            self.assertEqual(len(notifications), 1)
            notification = notifications[0]
            self.assertEqual(notification.session_id, session_id)
            self.assertEqual(notification.timestamp,
                             flow_manager.frozen_timestamp)

        self.assertEqual(RESULTS, ["Response 1"])

        # The last missing piece of request 2 is the actual status message.
        flow_manager.QueueResponse(status)
        flow_manager.Flush()

        # Now make sure request 2 runs as expected.
        worker_obj.RunOnce()
        worker_obj.thread_pool.Join()

        self.assertEqual(RESULTS, ["Response 1", "Response 2"])
コード例 #6
0
ファイル: administrative_test.py プロジェクト: qsdj/grr
    def testAlertEmailIsSentWhenClientKilled(self):
        """Test that client killed messages are handled correctly."""
        client_id = self.SetupClient(0)
        self.SetupTestClientObject(0)

        self.email_messages = []

        def SendEmail(address, sender, title, message, **_):
            self.email_messages.append(
                dict(address=address,
                     sender=sender,
                     title=title,
                     message=message))

        with utils.Stubber(email_alerts.EMAIL_ALERTER, "SendEmail", SendEmail):
            client = flow_test_lib.CrashClientMock(client_id, self.token)
            flow_test_lib.TestFlowHelper(
                flow_test_lib.FlowWithOneClientRequest.__name__,
                client,
                client_id=client_id,
                token=self.token,
                check_flow_errors=False)

        self.assertEqual(len(self.email_messages), 1)
        email_message = self.email_messages[0]

        # We expect the email to be sent.
        self.assertEqual(email_message.get("address", ""),
                         config.CONFIG["Monitoring.alert_email"])
        self.assertTrue(str(client_id) in email_message["title"])

        # Make sure the flow state is included in the email message.
        for s in [
                "flow_name", flow_test_lib.FlowWithOneClientRequest.__name__,
                "current_state"
        ]:
            self.assertTrue(s in email_message["message"])

        flow_obj = aff4.FACTORY.Open(client.flow_id,
                                     age=aff4.ALL_TIMES,
                                     token=self.token)
        self.assertEqual(flow_obj.context.state,
                         rdf_flow_runner.FlowContext.State.ERROR)

        # Make sure client object is updated with the last crash.

        # AFF4.
        client_obj = aff4.FACTORY.Open(client_id, token=self.token)
        crash = client_obj.Get(client_obj.Schema.LAST_CRASH)
        self.CheckCrash(crash, flow_obj.session_id, client_id)

        # Relational db.
        crash = data_store.REL_DB.ReadClientCrashInfo(client_id.Basename())
        self.CheckCrash(crash, flow_obj.session_id, client_id)

        # Make sure crashes collections are created and written
        # into proper locations. First check the per-client crashes collection.
        client_crashes = sorted(list(
            aff4_grr.VFSGRRClient.CrashCollectionForCID(client_id)),
                                key=lambda x: x.timestamp)

        self.assertTrue(len(client_crashes) >= 1)
        crash = list(client_crashes)[0]
        self.CheckCrash(crash, flow_obj.session_id, client_id)

        # Check per-flow crash collection. Check that crash written there is
        # equal to per-client crash.
        flow_crashes = sorted(list(
            flow_obj.GetValuesForAttribute(flow_obj.Schema.CLIENT_CRASH)),
                              key=lambda x: x.timestamp)
        self.assertEqual(len(flow_crashes), len(client_crashes))
        for a, b in zip(flow_crashes, client_crashes):
            self.assertEqual(a, b)
コード例 #7
0
ファイル: foreman_test.py プロジェクト: rainser/grr
  def testIntegerComparisons(self):
    """Tests that we can use integer matching rules on the foreman."""

    base_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1336480583.077736)
    boot_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1336300000.000000)

    self.SetupClient(0x11, system="Windows XP", install_time=base_time)
    self.SetupClient(0x12, system="Windows 7", install_time=base_time)
    # This one was installed one week earlier.
    one_week_ago = base_time - rdfvalue.Duration("1w")
    self.SetupClient(0x13, system="Windows 7", install_time=one_week_ago)
    self.SetupClient(0x14, system="Windows 7", last_boot_time=boot_time)

    with utils.Stubber(flow, "StartFlow", self.StartFlow):
      # Now setup the filters
      now = rdfvalue.RDFDatetime.Now()
      expires = now + rdfvalue.Duration("1h")
      foreman_obj = foreman.GetForeman(token=self.token)

      # Make a new rule
      rule = foreman_rules.ForemanRule(
          created=now, expires=expires, description="Test rule(old)")

      # Matches the old client
      one_hour_ago = base_time - rdfvalue.Duration("1h")
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
              integer=foreman_rules.ForemanIntegerClientRule(
                  field="INSTALL_TIME",
                  operator=foreman_rules.ForemanIntegerClientRule.Operator.
                  LESS_THAN,
                  value=one_hour_ago.AsSecondsSinceEpoch()))
      ])

      old_flow = "Test flow for old clients"
      # Will run Test Flow
      rule.actions.Append(
          flow_name=old_flow, argv=rdf_protodict.Dict(dict(foo="bar")))

      # Clear the rule set and add the new rule to it.
      rule_set = foreman_obj.Schema.RULES()
      rule_set.Append(rule)

      # Make a new rule
      rule = foreman_rules.ForemanRule(
          created=now, expires=expires, description="Test rule(new)")

      # Matches the newer clients
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
              integer=foreman_rules.ForemanIntegerClientRule(
                  field="INSTALL_TIME",
                  operator=foreman_rules.ForemanIntegerClientRule.Operator.
                  GREATER_THAN,
                  value=one_hour_ago.AsSecondsSinceEpoch()))
      ])

      new_flow = "Test flow for newer clients"

      # Will run Test Flow
      rule.actions.Append(
          flow_name=new_flow, argv=rdf_protodict.Dict(dict(foo="bar")))

      rule_set.Append(rule)

      # Make a new rule
      rule = foreman_rules.ForemanRule(
          created=now, expires=expires, description="Test rule(eq)")

      # Note that this also tests the handling of nonexistent attributes.
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
              integer=foreman_rules.ForemanIntegerClientRule(
                  field="LAST_BOOT_TIME",
                  operator="EQUAL",
                  value=boot_time.AsSecondsSinceEpoch()))
      ])

      eq_flow = "Test flow for LAST_BOOT_TIME"

      rule.actions.Append(
          flow_name=eq_flow, argv=rdf_protodict.Dict(dict(foo="bar")))

      rule_set.Append(rule)

      # Assign it to the foreman
      foreman_obj.Set(foreman_obj.Schema.RULES, rule_set)
      foreman_obj.Close()

      self.clients_launched = []
      foreman_obj.AssignTasksToClient("C.1000000000000011")
      foreman_obj.AssignTasksToClient("C.1000000000000012")
      foreman_obj.AssignTasksToClient("C.1000000000000013")
      foreman_obj.AssignTasksToClient("C.1000000000000014")

      # Make sure that the clients ran the correct flows.
      self.assertEqual(len(self.clients_launched), 4)
      self.assertEqual(self.clients_launched[0][0],
                       rdf_client.ClientURN("C.1000000000000011"))
      self.assertEqual(self.clients_launched[0][1], new_flow)
      self.assertEqual(self.clients_launched[1][0],
                       rdf_client.ClientURN("C.1000000000000012"))
      self.assertEqual(self.clients_launched[1][1], new_flow)
      self.assertEqual(self.clients_launched[2][0],
                       rdf_client.ClientURN("C.1000000000000013"))
      self.assertEqual(self.clients_launched[2][1], old_flow)
      self.assertEqual(self.clients_launched[3][0],
                       rdf_client.ClientURN("C.1000000000000014"))
      self.assertEqual(self.clients_launched[3][1], eq_flow)
コード例 #8
0
ファイル: fileview_test.py プロジェクト: qsdj/grr
    def testVersionDropDownChangesFileContentAndDownloads(self):
        """Test the fileview interface."""

        self.Open("/#/clients/%s" % self.client_id)

        # Go to Browse VFS.
        self.Click("css=a[grrtarget='client.vfs']")

        self.Click("css=#_fs i.jstree-icon")
        self.Click("css=#_fs-os i.jstree-icon")
        self.Click("css=#_fs-os-c i.jstree-icon")

        # Test file versioning.
        self.WaitUntil(self.IsElementPresent, "css=#_fs-os-c-Downloads")
        self.Click("link=Downloads")

        # Verify that we have the latest version in the table by default.
        self.assertTrue(
            gui_test_lib.DateString(gui_test_lib.TIME_2) in self.GetText(
                "css=tr:contains(\"a.txt\")"))

        # Click on the row.
        self.Click("css=tr:contains(\"a.txt\")")
        self.WaitUntilContains("a.txt", self.GetText,
                               "css=div#main_bottomPane h1")
        self.WaitUntilContains("HEAD", self.GetText,
                               "css=.version-dropdown > option[selected]")

        self.WaitUntilContains(gui_test_lib.DateString(gui_test_lib.TIME_2),
                               self.GetText,
                               "css=.version-dropdown > option:nth(1)")

        # Check the data in this file.
        self.Click("css=li[heading=TextView]")
        self.WaitUntilContains("Goodbye World", self.GetText,
                               "css=div.monospace pre")

        downloaded_files = []

        def FakeDownloadHandle(unused_self, args, token=None):
            _ = token  # Avoid unused variable linter warnings.
            aff4_path = args.client_id.ToClientURN().Add(args.file_path)
            age = args.timestamp or aff4.NEWEST_TIME
            downloaded_files.append((aff4_path, age))

            return api_call_handler_base.ApiBinaryStream(
                filename=aff4_path.Basename(), content_generator=xrange(42))

        with utils.Stubber(api_vfs.ApiGetFileBlobHandler, "Handle",
                           FakeDownloadHandle):
            # Try to download the file.
            self.Click("css=li[heading=Download]")

            self.WaitUntilContains(
                gui_test_lib.DateTimeString(gui_test_lib.TIME_2), self.GetText,
                "css=grr-file-download-view")
            self.Click("css=button:contains(\"Download\")")

            # Select the previous version.
            self.Click(
                "css=select.version-dropdown > option:contains(\"%s\")" %
                gui_test_lib.DateString(gui_test_lib.TIME_1))

            # Now we should have a different time.
            self.WaitUntilContains(
                gui_test_lib.DateTimeString(gui_test_lib.TIME_1), self.GetText,
                "css=grr-file-download-view")
            self.Click("css=button:contains(\"Download\")")

            self.WaitUntil(self.IsElementPresent, "css=li[heading=TextView]")

            # the FakeDownloadHandle method was actually called four times, since
            # a file download first sends a HEAD request to check user access.
            self.WaitUntil(lambda: len(downloaded_files) == 4)

        # Both files should be the same...
        self.assertEqual(downloaded_files[0][0],
                         u"aff4:/%s/fs/os/c/Downloads/a.txt" % self.client_id)
        self.assertEqual(downloaded_files[2][0],
                         u"aff4:/%s/fs/os/c/Downloads/a.txt" % self.client_id)
        # But from different times. The downloaded file timestamp is only accurate
        # to the nearest second. Also, the HEAD version of the file is downloaded
        # with age=NEWEST_TIME.
        self.assertEqual(downloaded_files[0][1], aff4.NEWEST_TIME)
        self.assertAlmostEqual(downloaded_files[2][1],
                               gui_test_lib.TIME_1,
                               delta=rdfvalue.Duration("1s"))

        self.Click("css=li[heading=TextView]")

        # Make sure the file content has changed. This version has "Hello World" in
        # it.
        self.WaitUntilContains("Hello World", self.GetText,
                               "css=div.monospace pre")
コード例 #9
0
ファイル: foreman_test.py プロジェクト: rainser/grr
  def testIntegerComparisons(self):
    """Tests that we can use integer matching rules on the foreman."""

    base_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1336480583.077736)
    boot_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1336300000.000000)

    self.SetupTestClientObject(
        0x11, system="Windows XP", install_time=base_time)
    self.SetupTestClientObject(0x12, system="Windows 7", install_time=base_time)
    # This one was installed one week earlier.
    one_week_ago = base_time - rdfvalue.Duration("1w")
    self.SetupTestClientObject(
        0x13, system="Windows 7", install_time=one_week_ago)
    self.SetupTestClientObject(
        0x14, system="Windows 7", last_boot_time=boot_time)

    with utils.Stubber(implementation.GRRHunt, "StartClients",
                       self.StartClients):
      now = rdfvalue.RDFDatetime.Now()
      expiration_time = now + rdfvalue.Duration("1h")

      # Make a new rule
      rule = foreman_rules.ForemanCondition(
          creation_time=now,
          expiration_time=expiration_time,
          description="Test rule(old)",
          hunt_name=standard.GenericHunt.__name__,
          hunt_id="H:111111")

      # Matches the old client
      one_hour_ago = base_time - rdfvalue.Duration("1h")
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
              integer=foreman_rules.ForemanIntegerClientRule(
                  field="INSTALL_TIME",
                  operator=foreman_rules.ForemanIntegerClientRule.Operator.
                  LESS_THAN,
                  value=one_hour_ago.AsSecondsSinceEpoch()))
      ])

      data_store.REL_DB.WriteForemanRule(rule)

      # Make a new rule
      rule = foreman_rules.ForemanCondition(
          creation_time=now,
          expiration_time=expiration_time,
          description="Test rule(new)",
          hunt_name=standard.GenericHunt.__name__,
          hunt_id="H:222222")

      # Matches the newer clients
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
              integer=foreman_rules.ForemanIntegerClientRule(
                  field="INSTALL_TIME",
                  operator=foreman_rules.ForemanIntegerClientRule.Operator.
                  GREATER_THAN,
                  value=one_hour_ago.AsSecondsSinceEpoch()))
      ])

      data_store.REL_DB.WriteForemanRule(rule)

      # Make a new rule
      rule = foreman_rules.ForemanCondition(
          creation_time=now,
          expiration_time=expiration_time,
          description="Test rule(eq)",
          hunt_name=standard.GenericHunt.__name__,
          hunt_id="H:333333")

      # Note that this also tests the handling of nonexistent attributes.
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
              integer=foreman_rules.ForemanIntegerClientRule(
                  field="LAST_BOOT_TIME",
                  operator="EQUAL",
                  value=boot_time.AsSecondsSinceEpoch()))
      ])

      data_store.REL_DB.WriteForemanRule(rule)

      foreman_obj = foreman.GetForeman()

      self.clients_started = []
      foreman_obj.AssignTasksToClient("C.1000000000000011")
      foreman_obj.AssignTasksToClient("C.1000000000000012")
      foreman_obj.AssignTasksToClient("C.1000000000000013")
      foreman_obj.AssignTasksToClient("C.1000000000000014")

      # Make sure that the clients ran the correct flows.
      self.assertEqual(len(self.clients_started), 4)
      self.assertEqual(self.clients_started[0][1], "C.1000000000000011")
      self.assertEqual("H:222222", self.clients_started[0][0].Basename())
      self.assertEqual(self.clients_started[1][1], "C.1000000000000012")
      self.assertEqual("H:222222", self.clients_started[1][0].Basename())
      self.assertEqual(self.clients_started[2][1], "C.1000000000000013")
      self.assertEqual("H:111111", self.clients_started[2][0].Basename())
      self.assertEqual(self.clients_started[3][1], "C.1000000000000014")
      self.assertEqual("H:333333", self.clients_started[3][0].Basename())
コード例 #10
0
 def __init__(self):
     self.stubber = utils.Stubber(report_plugins.REGISTRY, "plugins", {
         "FooReportPlugin": FooReportPlugin,
         "BarReportPlugin": BarReportPlugin
     })
コード例 #11
0
    def _testUpdateSparseImageChunks(self):
        """Make sure the right chunks get updated when we read a sparse file."""
        filename = "bigfile.txt"
        path = os.path.join(self.temp_dir, filename)
        chunksize = aff4_standard.AFF4SparseImage.chunksize

        # 8 chunks of data.
        contents = "bigdata!" * chunksize
        # We want to start reading in the middle of a chunk.
        start_point = int(2.5 * chunksize)
        read_len = int(2.5 * chunksize)

        client_path = self.ClientPathToAFF4Path(path)

        with open(path, "wb") as f:
            f.seek(start_point)
            f.write(contents)

        # Update the directory listing so we can see the file.
        self.ListDirectoryOnClient(self.temp_dir)

        # Make sure refreshing is allowed.
        with utils.Stubber(self.grr_fuse, "max_age_before_refresh",
                           datetime.timedelta(seconds=0)):
            # Read 3 chunks, from #2 to #4.
            data = self.grr_fuse.Read(client_path,
                                      length=read_len,
                                      offset=start_point)
            self.assertEqual(data,
                             contents[start_point:start_point + read_len],
                             "Fuse contents don't match.")

        # Make sure it's an AFF4SparseImage
        fd = aff4.FACTORY.Open(client_path, mode="rw", token=self.token)
        self.assertIsInstance(fd, aff4_standard.AFF4SparseImage)

        missing_chunks = self.grr_fuse.GetMissingChunks(fd,
                                                        length=10 * chunksize,
                                                        offset=0)
        # 10 chunks but not #2 - #4 that we already got.
        self.assertEqual(missing_chunks, [0, 1, 5, 6, 7, 8, 9])

        # Make sure refreshing is allowed.
        with utils.Stubber(self.grr_fuse, "max_age_before_refresh",
                           datetime.timedelta(seconds=0)):
            # Now we read and make sure the contents are as we expect.
            fuse_contents = self.grr_fuse.Read(client_path,
                                               length=8 * chunksize,
                                               offset=0)
            expected_contents = ("\x00" * start_point + contents)[:8 *
                                                                  chunksize]

        self.assertEqual(fuse_contents, expected_contents,
                         "Fuse contents don't match.")

        expected_contents = ("Y" * start_point + contents)[:8 * chunksize]

        # Now, we'll write to the file in those previously missing chunks.
        with open(path, "wb+") as f:
            f.seek(0)
            f.write(expected_contents)

        # Enable refresh.
        with utils.Stubber(self.grr_fuse, "max_age_before_refresh",
                           datetime.timedelta(seconds=0)):
            fuse_contents = self.grr_fuse.Read(client_path,
                                               length=len(contents),
                                               offset=0)

        self.assertEqual(fuse_contents, expected_contents,
                         "Fuse contents don't match.")

        # Put a cache time back on, all chunks should be not missing.
        self.grr_fuse.max_age_before_refresh = datetime.timedelta(seconds=30)
        missing_chunks = self.grr_fuse.GetMissingChunks(fd,
                                                        length=8 * chunksize,
                                                        offset=0)

        self.assertEqual(missing_chunks, [])
コード例 #12
0
ファイル: filesystem_test.py プロジェクト: qsdj/grr
    def testGlob(self):
        """Test that glob works properly."""
        client_id = self.SetupClient(0)

        # Add some usernames we can interpolate later.
        client = aff4.FACTORY.Open(client_id, mode="rw", token=self.token)
        kb = client.Get(client.Schema.KNOWLEDGE_BASE)
        kb.MergeOrAddUser(rdf_client.User(username="******"))
        kb.MergeOrAddUser(rdf_client.User(username="******"))
        client.Set(kb)
        client.Close()

        client_mock = action_mocks.GlobClientMock()

        # This glob selects all files which start with the username on this system.
        paths = [
            os.path.join(self.base_path, "%%Users.username%%*"),
            os.path.join(self.base_path, "VFSFixture/var/*/wtmp")
        ]

        # Set iterator really low to force iteration.
        with utils.Stubber(filesystem.Glob, "FILE_MAX_PER_DIR", 2):
            flow_test_lib.TestFlowHelper(
                filesystem.Glob.__name__,
                client_mock,
                client_id=client_id,
                paths=paths,
                pathtype=rdf_paths.PathSpec.PathType.OS,
                token=self.token,
                sync=False,
                check_flow_errors=False)

        output_path = client_id.Add("fs/os").Add(
            self.base_path.replace("\\", "/"))

        children = []
        fd = aff4.FACTORY.Open(output_path, token=self.token)
        for child in fd.ListChildren():
            filename = child.Basename()
            if filename != "VFSFixture":
                children.append(filename)

        expected = [
            filename for filename in os.listdir(self.base_path)
            if filename.startswith("test") or filename.startswith("syslog")
        ]
        self.assertTrue([x for x in expected if x.startswith("test")],
                        "Need a file starting with 'test'"
                        " in test_data for this test!")
        self.assertTrue([x for x in expected if x.startswith("syslog")],
                        "Need a file starting with 'syslog'"
                        " in test_data for this test!")
        self.assertItemsEqual(expected, children)

        children = []
        fd = aff4.FACTORY.Open(output_path.Add("VFSFixture/var/log"),
                               token=self.token)
        for child in fd.ListChildren():
            children.append(child.Basename())

        self.assertItemsEqual(children, ["wtmp"])
コード例 #13
0
  def testGetClientSummary(self):
    hostname = "test"
    system = "Linux"
    os_release = "12.02"
    kernel = "3.15-rc2"
    fqdn = "test.test.com"
    arch = "amd64"
    install_time = rdfvalue.RDFDatetime.Now()
    user = "******"
    userobj = rdf_client.User(username=user)
    interface = rdf_client.Interface(ifname="eth0")
    google_cloud_instance = rdf_cloud.GoogleCloudInstance(
        instance_id="1771384456894610289",
        zone="projects/123456789733/zones/us-central1-a",
        project_id="myproject",
        unique_id="us-central1-a/myproject/1771384456894610289")
    cloud_instance = rdf_cloud.CloudInstance(
        cloud_type="GOOGLE", google=google_cloud_instance)

    serial_number = "DSD33679FZ"
    system_manufacturer = "Foobar Inc."
    system_uuid = "C31292AD-6Z4F-55D8-28AC-EC1100E42222"
    hwinfo = rdf_client.HardwareInfo(
        serial_number=serial_number,
        system_manufacturer=system_manufacturer,
        system_uuid=system_uuid)

    timestamp = 1
    with utils.Stubber(time, "time", lambda: timestamp):
      with aff4.FACTORY.Create(
          "C.0000000000000000",
          aff4_grr.VFSGRRClient,
          mode="rw",
          token=self.token) as fd:
        kb = rdf_client.KnowledgeBase()
        kb.users.Append(userobj)
        empty_summary = fd.GetSummary()
        self.assertEqual(empty_summary.client_id, "C.0000000000000000")
        self.assertFalse(empty_summary.system_info.version)
        self.assertEqual(empty_summary.timestamp.AsSecondsSinceEpoch(), 1)

        # This will cause TYPE to be written with current time = 101 when the
        # object is closed
        timestamp += 100
        fd.Set(fd.Schema.HOSTNAME(hostname))
        fd.Set(fd.Schema.SYSTEM(system))
        fd.Set(fd.Schema.OS_RELEASE(os_release))
        fd.Set(fd.Schema.KERNEL(kernel))
        fd.Set(fd.Schema.FQDN(fqdn))
        fd.Set(fd.Schema.ARCH(arch))
        fd.Set(fd.Schema.INSTALL_DATE(install_time))
        fd.Set(fd.Schema.KNOWLEDGE_BASE(kb))
        fd.Set(fd.Schema.USERNAMES([user]))
        fd.Set(fd.Schema.HARDWARE_INFO(hwinfo))
        fd.Set(fd.Schema.INTERFACES([interface]))
        fd.Set(fd.Schema.CLOUD_INSTANCE(cloud_instance))

      with aff4.FACTORY.Open(
          "C.0000000000000000",
          aff4_grr.VFSGRRClient,
          mode="rw",
          token=self.token) as fd:
        summary = fd.GetSummary()
        self.assertEqual(summary.system_info.system, system)
        self.assertEqual(summary.system_info.release, os_release)
        self.assertEqual(summary.system_info.kernel, kernel)
        self.assertEqual(summary.system_info.fqdn, fqdn)
        self.assertEqual(summary.system_info.machine, arch)
        self.assertEqual(summary.system_info.install_date, install_time)
        self.assertItemsEqual(summary.users, [userobj])
        self.assertItemsEqual(summary.interfaces, [interface])
        self.assertFalse(summary.client_info)

        self.assertEqual(summary.timestamp.AsSecondsSinceEpoch(), 101)
        self.assertEqual(summary.cloud_type, "GOOGLE")
        self.assertEqual(summary.cloud_instance_id,
                         "us-central1-a/myproject/1771384456894610289")

        self.assertEqual(summary.serial_number, serial_number)
        self.assertEqual(summary.system_manufacturer, system_manufacturer)
        self.assertEqual(summary.system_uuid, system_uuid)