示例#1
0
 def rows(self):
     rows = []
     event_ids = navigation_event_ids_by_user(self.selected_user,
                                              self.datespan.startdate,
                                              self.datespan.enddate)
     for event_doc in iter_docs(NavigationEventAudit.get_db(), event_ids):
         event = NavigationEventAudit.wrap(event_doc)
         if not self.selected_domain or self.selected_domain == event.domain:
             rows.append([
                 event.event_date, event.user, event.domain or '',
                 event.ip_address, event.request_path
             ])
     return rows
    def test_copy(self):
        def _assert():
            self.assertEqual(NavigationEventAudit.objects.count(), 3)
            self.assertEqual([
                e.path for e in NavigationEventAudit.objects.order_by(
                    "-event_date").all()
            ], [
                "just/a/checkpoint", '/a/random/phone/restore/',
                '/a/test-space/phone/restore/'
            ])
            self.assertEqual([
                e.params for e in NavigationEventAudit.objects.order_by(
                    "-event_date").all()
            ], ["", "version=2.0&since=...", "version=2.0&since=..."])
            self.assertEqual(AccessAudit.objects.count(), 1)
            self.assertEqual(AccessAudit.objects.first().path,
                             "/a/delmar/login/")

        NavigationEventAudit(event_date=datetime(2021, 2, 1, 4),
                             path="just/a/checkpoint").save()
        copy_events_to_sql(start_time=datetime(2021, 2, 1, 5),
                           end_time=datetime(2021, 2, 1, 1, 59),
                           batch_size=10)
        _assert()

        # Re-copying should have no effect
        copy_events_to_sql(start_time=datetime(2021, 2, 1, 5),
                           end_time=datetime(2021, 2, 1, 2),
                           batch_size=10)
        _assert()
示例#3
0
 def test_audit_trace_id_header(self):
     trace_id = "Root=1-67891233-abcdef012345678912345678"
     with patch_trace_id_header():
         view = make_view()
         request = make_request(**{to_django_header(TRACE_HEADER): trace_id})
         event = NavigationEventAudit.audit_view(request, "*****@*****.**", view, {})
     self.assertEqual(event.headers[to_django_header(TRACE_HEADER)], trace_id)
     event.save()
示例#4
0
 def test_audit_view_should_truncate_params(self):
     path = "/path"
     view = make_view(path)
     request = make_request(path,
                            params={f"a{x}": "b"
                                    for x in range(1000)})
     event = NavigationEventAudit.audit_view(request, "*****@*****.**",
                                             view, {})
     event.save()
     event.refresh_from_db()
     self.assertEqual(len(event.params), 4096)
示例#5
0
 def test_audit_view_should_set_properties(self):
     path = "/a/block/path"
     view = make_view(path)
     request = make_request(path)
     event = NavigationEventAudit.audit_view(request, "*****@*****.**", view, {})
     self.assertEqual(event.path, path)
     self.assertEqual(event.domain, "block")
     self.assertEqual(event.request_path, f"{path}?key=value")
     self.assertEqual(event.description, "*****@*****.**")
     self.assertNotIn(to_django_header(TRACE_HEADER), event.headers)
     event.save()
示例#6
0
 def create_session_events(domain):
     login_event = dict(
         user=self.username,
         domain=domain,
         session_key=uuid.uuid4().hex,
         event_date=datetime.utcnow(),
     )
     for event_domain, minutes in [(None, -1),
                                   (domain, 0),
                                   (domain, 1)]:
         fields = login_event.copy()
         # save one event with domain/date changed by loop params:
         fields["domain"] = event_domain
         fields['event_date'] += timedelta(minutes=minutes)
         NavigationEventAudit(**fields).save()
         # update the fields and save another:
         #   - same session
         #   - different domain
         #   - 5 minutes ealier
         fields["domain"] = "not-queried"
         fields["event_date"] += timedelta(minutes=-5)
         NavigationEventAudit(**fields).save()
     return login_event
示例#7
0
 def test_audit_view_should_not_save(self):
     view = make_view()
     event = NavigationEventAudit.audit_view(self.request, "username", view,
                                             {})
     self.assertIsNone(event._id)
示例#8
0
 def test_audit_view_should_not_save(self):
     view = make_view()
     event = NavigationEventAudit.audit_view(make_request(),
                                             "*****@*****.**", view, {})
     self.assertIsNone(event.id)
示例#9
0
def get_events_from_couch(batch_start_key, start_key, end_key, batch_size, start_doc_id=None):
    navigation_objects = []
    access_objects = []
    records_returned = 0
    next_start_key = None
    nav_couch_ids = []
    access_couch_ids = []
    other_doc_type_count = 0
    processed_doc_id = start_doc_id
    couch_docs = _get_couch_docs(start_key, end_key, batch_size, start_doc_id)
    for result in couch_docs:
        next_start_key = result['key']
        records_returned += 1
        doc = result["doc"]
        kwargs = _pick(doc, ["user", "domain", "ip_address", "session_key",
                            "status_code", "user_agent"])
        kwargs.update({
            "event_date": force_to_datetime(doc.get("event_date")),
            "couch_id": doc["_id"],
        })
        processed_doc_id = doc["_id"]
        if doc["doc_type"] == "NavigationEventAudit":
            nav_couch_ids.append(doc['_id'])
            kwargs.update(_pick(doc, ["headers", "status_code", "view", "view_kwargs"]))
            # Postgres does not play well with control characters in strings
            # Some crafted URLs can contain these charachters, so replacing them with '' in request_path
            # https://stackoverflow.com/a/14946355/3537212
            request_path = re.sub(
                r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff]',
                lambda match: repr(match.group(0)),
                doc.get("request_path", "")
            )
            path, _, params = request_path.partition("?")
            kwargs.update({
                "path": path,
                "params": params,
            })
            navigation_objects.append(NavigationEventAudit(**kwargs))
        elif doc["doc_type"] == "AccessAudit":
            access_couch_ids.append(doc['_id'])
            kwargs.update(_pick(doc, ["http_accept", "trace_id"]))
            access_type = doc.get('access_type')
            kwargs.update({
                "access_type": ACCESS_LOOKUP.get(doc.get("access_type")),
                "path": doc.get("path_info"),
            })
            if access_type == "logout":
                kwargs.update({"path": "accounts/logout"})
            access_objects.append(AccessAudit(**kwargs))
        else:
            assert doc["doc_type"] in IGNORED_DOC_TYPES, doc
            other_doc_type_count += 1
    res_obj = get_unsaved_events(
        navigation_objects,
        access_objects,
        nav_couch_ids,
        access_couch_ids,
        batch_start_key,
        end_key
    )

    res_obj.update({
        "break_query": records_returned < batch_size or not next_start_key,
        "next_start_key": next_start_key,
        "last_doc_id": processed_doc_id,
        "other_doc_type_count": other_doc_type_count
    })
    return res_obj