Exemple #1
0
    def _RunUpdateFlow(self, client_id):
        # Get the flows that should have been started and finish them.
        fd = aff4.FACTORY.Open(client_id.Add("flows"), token=self.token)
        flows = list(fd.ListChildren())

        gui_test_lib.CreateFileVersion(client_id,
                                       "fs/os/c/a.txt",
                                       "Hello World",
                                       timestamp=gui_test_lib.TIME_0,
                                       token=self.token)
        gui_test_lib.CreateFolder(client_id,
                                  "fs/os/c/TestFolder",
                                  timestamp=gui_test_lib.TIME_0,
                                  token=self.token)
        gui_test_lib.CreateFolder(client_id,
                                  "fs/os/c/bin/TestBinFolder",
                                  timestamp=gui_test_lib.TIME_0,
                                  token=self.token)

        client_mock = action_mocks.ActionMock()
        for flow_urn in flows:
            flow_test_lib.TestFlowHelper(flow_urn,
                                         client_mock,
                                         client_id=client_id,
                                         token=self.token,
                                         check_flow_errors=False)
    def testApprovalExpiry(self):
        """Tests that approvals expire after the correct time."""
        client_id = self.SetupClient(0)
        gui_test_lib.CreateFileVersion(client_id,
                                       "fs/os/foo",
                                       token=self.token)

        with self.assertRaises(grr_api_errors.AccessForbiddenError):
            self.api.Client(client_id.Basename()).File("fs/os/foo").Get()

        with test_lib.FakeTime(100.0, increment=1e-3):
            self.RequestAndGrantClientApproval(client_id,
                                               requestor=self.token.username)

            # This should work now.
            self.api.Client(client_id.Basename()).File("fs/os/foo").Get()

        token_expiry = config.CONFIG["ACL.token_expiry"]

        # Make sure the caches are reset.
        self.ClearCache()

        # This is close to expiry but should still work.
        with test_lib.FakeTime(100.0 + token_expiry - 100.0):
            self.api.Client(client_id.Basename()).File("fs/os/foo").Get()

        # Make sure the caches are reset.
        self.ClearCache()

        # Past expiry, should fail.
        with test_lib.FakeTime(100.0 + token_expiry + 100.0):
            with self.assertRaises(grr_api_errors.AccessForbiddenError):
                self.api.Client(client_id.Basename()).File("fs/os/foo").Get()
Exemple #3
0
    def testNavigateToFileInFilesView(self):
        gui_test_lib.CreateFileVersion(self.client_id,
                                       "fs/os/foofolder/subfolder/barfile",
                                       "Hello VFS View".encode("utf-8"),
                                       timestamp=gui_test_lib.TIME_1)

        self.Open(f"/v2/clients/{self.client_id}")

        self.Click("css=a.collected-files-tab")

        self.WaitUntilContains("files", self.GetCurrentUrlPath)

        self.Click("css=mat-tree a:contains('foofolder')")

        self.Click("css=mat-tree a:contains('subfolder')")

        self.Click("css=table.directory-table td:contains('barfile')")

        self.WaitUntilContains("barfile", self.GetCurrentUrlPath)

        self.WaitUntilContains("st_size 14 B", self.GetText,
                               "css=app-stat-view")

        self.Click("css=a.mat-tab-link:contains('Text content')")

        self.WaitUntilContains("text", self.GetCurrentUrlPath)

        self.WaitUntilContains("Hello VFS View", self.GetText,
                               "css=app-file-details")
Exemple #4
0
  def testUrlSensitiveCharactersAreShownInTree(self):
    gui_test_lib.CreateFileVersion(
        self.client_id,
        "fs/os/c/foo?bar&oh/a&=?b.txt",
        "Hello World".encode("utf-8"),
        timestamp=gui_test_lib.TIME_1,
        token=self.token)

    # Open VFS view for client 1 on a specific location.
    self.Open("/#/clients/C.0000000000000001/vfs/fs/os/c/")

    # Wait until the folder gets selected and its information displayed in
    # the details pane.
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-file-details:contains('VFSDirectory')")

    # Click on the "foo?bar&oh" subfolder.
    self.Click("css=#_fs-os-c-foo_3Fbar_26oh a:visible")

    # Some more unicode testing.
    self.Click(u"css=tr:contains(\"a&=?b.txt\")")
    self.Click("css=li[heading=Download]")

    self.WaitUntil(self.IsElementPresent,
                   "css=grr-file-details:contains('a&=?b.txt')")

    # Test the text viewer.
    self.Click("css=li[heading=TextView]")
    self.WaitUntilContains("Hello World", self.GetText, "css=div.monospace pre")
  def testSimpleUnauthorizedAccess(self):
    """Tests that simple access requires a token."""
    client_id = self.SetupClient(0)
    gui_test_lib.CreateFileVersion(client_id, "fs/os/foo")

    with self.assertRaises(grr_api_errors.AccessForbiddenError):
      self.api.Client(client_id).File("fs/os/foo").Get()
Exemple #6
0
    def testFolderPathWithUnicodeCharactersCanBeClicked(self):
        dirpath = "fs/os/home/user/foo/a看a"
        filepath = f"{dirpath}/bar/baz.txt"

        gui_test_lib.CreateFileVersion(self.client_id, filepath, b"foobar")

        self.Open(f"/#/clients/{self.client_id}/vfs/{dirpath}")
        self.Click("css=li > a:contains(\"a看a\")")
        self.Click("css=li > a:contains(\"bar\")")
        self.WaitUntil(self.IsElementPresent, "css=tr:contains(\"baz.txt\")")
    def GenerateNotifications(cls, client_id, token):
        """Generates fake notifications of different notification types."""
        session_id = flow_test_lib.StartFlow(discovery.Interrogate,
                                             client_id=client_id,
                                             creator=token.username)

        notification.Notify(
            token.username,
            rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED,
            "Fake discovery message",
            rdf_objects.ObjectReference(
                reference_type=rdf_objects.ObjectReference.Type.CLIENT,
                client=rdf_objects.ClientReference(
                    client_id=client_id.Basename())))

        # ViewObject: VirtualFileSystem
        notification.Notify(
            token.username,
            rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED,
            "File fetch completed",
            rdf_objects.ObjectReference(
                reference_type=rdf_objects.ObjectReference.Type.VFS_FILE,
                vfs_file=rdf_objects.VfsFileReference(
                    client_id=client_id.Basename(),
                    path_type=rdf_objects.PathInfo.PathType.OS,
                    path_components=["proc", "10", "exe"])))

        gui_test_lib.CreateFileVersion(client_id,
                                       "fs/os/proc/10/exe",
                                       b"",
                                       timestamp=gui_test_lib.TIME_0,
                                       token=token)

        # ViewObject: Flow
        notification.Notify(
            token.username,
            rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED,
            "Fake view flow message",
            rdf_objects.ObjectReference(
                reference_type=rdf_objects.ObjectReference.Type.FLOW,
                flow=rdf_objects.FlowReference(client_id=client_id.Basename(),
                                               flow_id=session_id)))

        # FlowError
        if data_store.RelationalDBEnabled():
            flow_base.TerminateFlow(client_id.Basename(), session_id,
                                    "Fake flow error")
        else:
            with aff4.FACTORY.Open(client_id.Add("flows").Add(session_id),
                                   mode="rw",
                                   token=token) as flow_obj:
                flow_obj.GetRunner().Error("Fake flow error")

        return session_id
Exemple #8
0
    def testShowsVfsFileContents(self):
        gui_test_lib.CreateFileVersion(self.client_id,
                                       "fs/os/foo/barfile",
                                       "Hello VFS View".encode("utf-8"),
                                       timestamp=gui_test_lib.TIME_1)

        self.Open(
            f"/v2/clients/{self.client_id}(drawer:files/os/%2Ffoo%2Fbarfile)")

        self.WaitUntilContains("/foo/barfile", self.GetText, "css=mat-drawer")
        self.WaitUntilContains("Hello VFS View", self.GetText,
                               "css=mat-drawer")
Exemple #9
0
  def _RunUpdateFlow(self, client_id):
    gui_test_lib.CreateFileVersion(
        client_id,
        "fs/os/c/a.txt",
        "Hello World".encode("utf-8"),
        timestamp=gui_test_lib.TIME_0)
    gui_test_lib.CreateFolder(
        client_id, "fs/os/c/TestFolder", timestamp=gui_test_lib.TIME_0)
    gui_test_lib.CreateFolder(
        client_id, "fs/os/c/bin/TestBinFolder", timestamp=gui_test_lib.TIME_0)

    flow_test_lib.FinishAllFlowsOnClient(client_id)
Exemple #10
0
    def testFolderPathCanContainUrlSensitiveCharacters(self):
        gui_test_lib.CreateFileVersion(self.client_id,
                                       "fs/os/c/foo?bar&oh/a&=?b.txt",
                                       "Hello World".encode("utf-8"),
                                       timestamp=gui_test_lib.TIME_1)

        # Open VFS view for client 1 on a location containing unicode characters.
        self.Open(
            "/#c=C.0000000000000001&main=VirtualFileSystemView&t=_fs-os-c"
            "-foo_3Fbar_26oh")

        # Check that the correct file is listed.
        self.WaitUntil(self.IsElementPresent, "css=tr:contains(\"a&=?b.txt\")")
Exemple #11
0
    def testShowsVfsFileStatInDrawer(self):
        gui_test_lib.CreateFileVersion(self.client_id,
                                       "fs/os/foo/barfile",
                                       "Hello VFS View".encode("utf-8"),
                                       timestamp=gui_test_lib.TIME_1)

        self.Open(
            f"/v2/clients/{self.client_id}(drawer:files/os/%2Ffoo%2Fbarfile/stat)"
        )

        self.WaitUntilContains("barfile", self.GetText, "css=mat-drawer")
        self.assertContainsInOrder([
            "SHA-256",
            "23406c404b29af3a449196db4833de182b9b955df14cef54fb6004189968c154"
        ], self.GetText("css=mat-drawer"))
Exemple #12
0
  def _RunUpdateFlow(self, client_id):
    gui_test_lib.CreateFileVersion(
        client_id,
        "fs/os/c/a.txt",
        "Hello World".encode("utf-8"),
        timestamp=gui_test_lib.TIME_0)
    gui_test_lib.CreateFolder(
        client_id, "fs/os/c/TestFolder", timestamp=gui_test_lib.TIME_0)
    gui_test_lib.CreateFolder(
        client_id, "fs/os/c/bin/TestBinFolder", timestamp=gui_test_lib.TIME_0)

    flow_test_lib.FinishAllFlowsOnClient(
        client_id,
        client_mock=action_mocks.MultiGetFileClientMock(),
        check_flow_errors=False)
  def testClientApproval(self):
    """Tests that we can create an approval object to access clients."""
    client_id = self.SetupClient(0)
    gui_test_lib.CreateFileVersion(client_id, "fs/os/foo")

    with self.assertRaises(grr_api_errors.AccessForbiddenError):
      self.api.Client(client_id).File("fs/os/foo").Get()

    self.RequestAndGrantClientApproval(client_id, requestor=self.token.username)
    self.api.Client(client_id).File("fs/os/foo").Get()

    # Move the clocks forward to make sure the approval expires.
    with test_lib.FakeTime(
        rdfvalue.RDFDatetime.Now() + config.CONFIG["ACL.token_expiry"],
        increment=1e-3):
      with self.assertRaises(grr_api_errors.AccessForbiddenError):
        self.api.Client(client_id).File("fs/os/foo").Get()
Exemple #14
0
    def GenerateNotifications(cls, client_id, username):
        """Generates fake notifications of different notification types."""
        session_id = flow_test_lib.StartFlow(discovery.Interrogate,
                                             client_id=client_id,
                                             creator=username)

        notification.Notify(
            username,
            rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED,
            "Fake discovery message",
            rdf_objects.ObjectReference(
                reference_type=rdf_objects.ObjectReference.Type.CLIENT,
                client=rdf_objects.ClientReference(client_id=client_id)))

        # ViewObject: VirtualFileSystem
        notification.Notify(
            username,
            rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED,
            "File fetch completed",
            rdf_objects.ObjectReference(
                reference_type=rdf_objects.ObjectReference.Type.VFS_FILE,
                vfs_file=rdf_objects.VfsFileReference(
                    client_id=client_id,
                    path_type=rdf_objects.PathInfo.PathType.OS,
                    path_components=["proc", "10", "exe"])))

        gui_test_lib.CreateFileVersion(client_id,
                                       "fs/os/proc/10/exe",
                                       b"",
                                       timestamp=gui_test_lib.TIME_0)

        # ViewObject: Flow
        notification.Notify(
            username,
            rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED,
            "Fake view flow message",
            rdf_objects.ObjectReference(
                reference_type=rdf_objects.ObjectReference.Type.FLOW,
                flow=rdf_objects.FlowReference(client_id=client_id,
                                               flow_id=session_id)))

        # FlowError
        flow_base.TerminateFlow(client_id, session_id, "Fake flow error")

        return session_id
Exemple #15
0
    def testTriggersMultiGetFilesFlow(self):
        gui_test_lib.CreateFileVersion(self.client_id,
                                       "fs/os/foo/barfile",
                                       "Hello VFS View".encode("utf-8"),
                                       timestamp=gui_test_lib.TIME_1)

        self.Open(
            f"/v2/clients/{self.client_id}(drawer:files/os/%2Ffoo%2Fbarfile)")

        self.WaitUntilContains("/foo/barfile", self.GetText, "css=mat-drawer")

        self.Click("css=button.recollect")
        self.Click("css=.mat-drawer-backdrop")
        self.WaitUntilNot(self.IsElementPresent, "css=mat-drawer")

        self.WaitUntil(
            self.IsElementPresent,
            "css=flow-details:contains('MultiGetFile') .title:contains('/foo/barfile')"
        )
Exemple #16
0
 def TouchFile(self, client_id, path):
     gui_test_lib.CreateFileVersion(client_id=client_id,
                                    path=path,
                                    token=self.token)
Exemple #17
0
    def testRefreshFileStartsFlow(self):
        self.Open("/")

        self.Type("client_query", "C.0000000000000001")
        self.Click("client_query_submit")

        self.WaitUntilEqual(u"C.0000000000000001", self.GetText,
                            "css=span[type=subject]")

        # Choose client 1.
        self.Click("css=td:contains('0001')")

        # Go to Browse VFS.
        self.Click("css=a:contains('Browse Virtual Filesystem')")

        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")

        # Select a file and start a flow by requesting a newer version.
        self.Click("css=tr:contains(\"a.txt\")")
        self.Click("css=li[heading=Download]")
        self.Click("css=button:contains(\"Collect from the client\")")

        # Create a new file version (that would have been created by the flow
        # otherwise) and finish the flow.
        client_id = rdf_client.ClientURN("C.0000000000000001")

        fd = aff4.FACTORY.Open(client_id.Add("flows"), token=self.token)

        # Make sure that the flow has started (when button is clicked, the HTTP
        # API request is sent asynchronously).
        def MultiGetFileStarted():
            return transfer.MultiGetFile.__name__ in list(
                x.__class__.__name__ for x in fd.OpenChildren())

        self.WaitUntil(MultiGetFileStarted)

        flows = list(fd.ListChildren())

        client_mock = action_mocks.MultiGetFileClientMock()
        for flow_urn in flows:
            flow_test_lib.TestFlowHelper(flow_urn,
                                         client_mock,
                                         client_id=client_id,
                                         check_flow_errors=False,
                                         token=self.token)

        time_in_future = rdfvalue.RDFDatetime.Now() + rdfvalue.Duration("1h")
        # We have to make sure that the new version will not be within a second
        # from the current one, otherwise the previous one and the new one will
        # be indistinguishable in the UI (as it has a 1s precision when
        # displaying versions).
        with test_lib.FakeTime(time_in_future):
            gui_test_lib.CreateFileVersion(
                rdf_client.ClientURN("C.0000000000000001"),
                "fs/os/c/Downloads/a.txt",
                "The newest version!",
                timestamp=rdfvalue.RDFDatetime.Now(),
                token=self.token)

        # Once the flow has finished, the file view should update and add the
        # newly created, latest version of the file to the list. The selected
        # option should still be "HEAD".
        self.WaitUntilContains("HEAD", self.GetText,
                               "css=.version-dropdown > option[selected]")

        # The file table should also update and display the new timestamp.
        self.WaitUntilContains(gui_test_lib.DateTimeString(time_in_future),
                               self.GetText,
                               "css=.version-dropdown > option:nth(1)")

        # The file table should also update and display the new timestamp.
        self.WaitUntil(
            self.IsElementPresent,
            "css=grr-file-table tbody > tr td:contains(\"%s\")" %
            (gui_test_lib.DateTimeString(time_in_future)))

        # Make sure the file content has changed.
        self.Click("css=li[heading=TextView]")
        self.WaitUntilContains("The newest version!", self.GetText,
                               "css=div.monospace pre")

        # Go to the flow management screen and check that there was a new flow.
        self.Click("css=a:contains('Manage launched flows')")
        self.Click("css=grr-flows-list tr:contains('MultiGetFile')")
        self.WaitUntilContains(transfer.MultiGetFile.__name__, self.GetText,
                               "css=#main_bottomPane")

        self.WaitUntilContains(
            "c/Downloads/a.txt", self.GetText,
            "css=#main_bottomPane table > tbody td.proto_key:contains(\"Path\") "
            "~ td.proto_value")
Exemple #18
0
    def testRefreshFileStartsFlow(self):
        self.Open("/#/clients/C.0000000000000001/vfs/fs/os/c/Downloads/")

        # Select a file and start a flow by requesting a newer version.
        self.Click("css=tr:contains(\"a.txt\")")
        self.Click("css=li[heading=Download]")
        self.Click("css=button:contains(\"Collect from the client\")")

        # Create a new file version (that would have been created by the flow
        # otherwise) and finish the flow.

        # Make sure that the flow has started (when button is clicked, the HTTP
        # API request is sent asynchronously).
        def MultiGetFileStarted():
            return compatibility.GetName(transfer.MultiGetFile) in [
                f.flow_class_name
                for f in data_store.REL_DB.ReadAllFlowObjects(
                    client_id=self.client_id)
            ]

        self.WaitUntil(MultiGetFileStarted)

        flow_test_lib.FinishAllFlowsOnClient(self.client_id,
                                             check_flow_errors=False)

        time_in_future = rdfvalue.RDFDatetime.Now() + rdfvalue.DurationSeconds(
            "1h")
        # We have to make sure that the new version will not be within a second
        # from the current one, otherwise the previous one and the new one will
        # be indistinguishable in the UI (as it has a 1s precision when
        # displaying versions).
        gui_test_lib.CreateFileVersion(self.client_id,
                                       "fs/os/c/Downloads/a.txt",
                                       "The newest version!".encode("utf-8"),
                                       timestamp=time_in_future)

        # Once the flow has finished, the file view should update and add the
        # newly created, latest version of the file to the list. The selected
        # option should still be "HEAD".
        self.WaitUntilContains("HEAD", self.GetText,
                               "css=.version-dropdown > option[selected]")

        # The file table should also update and display the new timestamp.
        self.WaitUntilContains(gui_test_lib.DateTimeString(time_in_future),
                               self.GetText,
                               "css=.version-dropdown > option:nth(1)")

        # The file table should also update and display the new timestamp.
        self.WaitUntil(
            self.IsElementPresent,
            "css=grr-file-table tbody > tr td:contains(\"%s\")" %
            (gui_test_lib.DateTimeString(time_in_future)))

        # Make sure the file content has changed.
        self.Click("css=li[heading=TextView]")
        self.WaitUntilContains("The newest version!", self.GetText,
                               "css=div.monospace pre")

        # Go to the flow management screen and check that there was a new flow.
        self.Click("css=a:contains('Manage launched flows')")
        self.Click("css=grr-flows-list tr:contains('MultiGetFile')")
        self.WaitUntilContains(transfer.MultiGetFile.__name__, self.GetText,
                               "css=#main_bottomPane")

        self.WaitUntilContains(
            "c/Downloads/a.txt", self.GetText,
            "css=#main_bottomPane table > tbody td.proto_key:contains(\"Path\") "
            "~ td.proto_value")