Exemplo n.º 1
0
def get(current, collection_id, part=0):
    """Stream the requested collection.

    Note that we do not edit the collection in any way we just stream the same
    thing the client sent to us. We rely on AppEngine's automatic blob store
    detection to stream the data from blob store by setting the right header in
    the response.
    """
    db = current.db
    response = current.response
    part = int(part)

    row = db(db.collections.collection_id == collection_id).select().first()
    if row:
        row = db((db.collections.collection_id == collection_id) &
                 (db.collections.part == part)).select().first()

        if row:
            response.headers[blobstore.BLOB_KEY_HEADER] = row.blob_key
            response.headers["Content-Type"] = "application/json"

            audit.log(current, "CollectionDownload", collection_id=collection_id)

        else:
            raise ValueError("collection not found")
Exemplo n.º 2
0
def clear_all_data(current):
    """Clears all the data."""
    db = current.db
    try:
        for table in TABLES:
            db(getattr(db, table).id > 0).delete()
    finally:
        audit.log(current, "DemoClearedTable")
Exemplo n.º 3
0
def approve_request(current, client_id, user, role):
    """Grant the approval for the client."""
    # Validate the client_id.
    if (client_id.startswith("C.") and len(client_id.split("/")) == 1 and
        role in ["Examiner", "Investigator"]):
        users.add(current, user, "/" + client_id, role)

    audit.log(current, "ApprovalGranted", client_id=client_id,
              approvee=user, role=role)

    return dict()
Exemplo n.º 4
0
def delete(current, user, role, resource="/"):
    """Remove a user binding."""
    db = current.db

    db((db.permissions.user == user) &
       (db.permissions.resource == resource) &
       (db.permissions.role == role)).delete()

    audit.log(current, "UserDelete", username=user, resource=resource, role=role)

    return {}
Exemplo n.º 5
0
def grant_approval(current, hunt_id, user):
    db = current.db
    row = db(db.hunts.hunt_id == hunt_id).select().first()
    if row and row.state == "Proposed":
        row.update_record(state="Started", timestamp=time.time())

        # Give the user permission over this hunt.
        users.add(current, user, "/" + hunt_id, "Examiner")
        return dict(data="ok")

    audit.log(current, "HuntApproval", hunt_id=hunt_id)

    return {}
Exemplo n.º 6
0
def request_approval(current, client_id, approver, role):
    """Request an approval from the specified user."""

    # Notify the approver that a request is pending.
    users.send_notifications(
        current, approver, "APPROVAL_REQUEST", dict(
            client_id=client_id,
            user=utils.get_current_username(current),
            role=role))

    audit.log(current, "ApprovalRequest", client_id=client_id,
              approver=approver, role=role)
    return {}
Exemplo n.º 7
0
def add(current, user, resource, role, condition="{}"):
    """Add a new user role grant."""
    db = current.db
    if role not in roles:
        raise ValueError("Role %s is not valid." % role)

    db.permissions.update_or_insert(
        dict(user=user, resource=resource, role=role),
        user=user,
        resource=resource,
        role=role,
        condition=types.IAMCondition.from_json(condition))

    audit.log(current, "UserAdd", username=user, resource=resource, role=role)

    return {}
Exemplo n.º 8
0
def download(current, upload_id, filename=None):
    db = current.db
    response = current.response
    if filename is None:
        filename = "download_" + upload_id

    row = db(db.uploads.id == upload_id).select().first()
    if row:
        response.headers[blobstore.BLOB_KEY_HEADER] = row.blob_key
        response.headers["Content-Type"] = "application/octet-stream"
        response.headers["Content-Disposition"] = (
            'attachment; filename="%s"' % html.xmlescape(filename))

        audit.log(current, "FileDownload", upload_id=upload_id)

    else:
        raise ValueError("not found")
Exemplo n.º 9
0
def search(current, query=None):
    if not query:
        raise ValueError("query must be provided.")

    query = query.strip()
    condition = current.db.clients.id > 0
    orderby = None

    audit.log(current, "ClientSearch", query=query)

    # Search for a client ID directly.
    if query.startswith("C."):
        condition = current.db.clients.client_id == query
    elif query.startswith("label:"):
        label = query.split(":", 1)[1]
        condition = (current.db.clients.labels == label) | (
            current.db.clients.custom_labels == label)
        orderby = current.db.clients.id
    else:
        # AppEngine uses Bigtable which does not support `like` operation. We
        # only support a prefix match.
        condition = ((current.db.clients.hostname >= query) &
                     (current.db.clients.hostname < query + u"\ufffd"))

    result = []
    for row in current.db(condition).select(
            orderby_on_limitby=False, limitby=(0, 1000),
            orderby=orderby):
        labels = set([x for x in row.labels if x])
        result.append(dict(
            last=row.last,
            last_humanized=humanize.naturaltime(
                datetime.datetime.now()-row.last),
            client_id=row.client_id,
            summary=json.loads(row.summary),
            labels=sorted(labels),
            # These are the only labels which may be modified.
            custom_labels=row.custom_labels))

    return dict(data=result)
Exemplo n.º 10
0
def propose_from_flows(current, flow_ids, labels, approvers, name=None):
    """Launch a hunt from the flows on these labels."""
    hunt_id = utils.new_hunt_id()
    now = time.time()
    also_upload_files = False

    result = agent.Flow.from_keywords(
        name=name or hunt_id,
        flow_id=hunt_id,
        created_time=now,
        creator=utils.get_current_username(current),
        ticket=dict(
            location=dict(
                __type__="HTTPLocation",
                base=utils.route_api('/control/hunt_ticket'),
                path_prefix=hunt_id,
            )),
    )

    db = current.db
    seen = set()
    for flow_id in flow_ids:
        row = db(db.flows.flow_id == flow_id).select().first()
        if row:
            for action in row.flow.actions:
                if action.rekall_session.get("also_upload_files"):
                    also_upload_files = True

                if isinstance(action, actions.PluginAction):
                    action = actions.PluginAction.from_keywords(
                        plugin=action.plugin,
                        rekall_session=action.rekall_session,
                        collection=dict(
                            __type__="JSONCollection",
                            location=dict(
                                __type__="BlobUploader",
                                base=html.URL(
                                    c="api", f="control", args=['upload'], host=True),
                                path_template=(
                                    "collection/%s/{part}" % hunt_id),
                            )),
                        args=action.args)

                    # Dedupe identical canned actions.
                    key = action.to_json()
                    if key in seen:
                        continue

                    seen.add(key)
                    result.actions.append(action)

    if also_upload_files:
        result.file_upload = dict(
            __type__="FileUploadLocation",
            flow_id=hunt_id,
            base=html.URL(c="api", f='control/file_upload',
                          host=True))

    # Add the hunt to the hunts table.
    db.hunts.insert(
        hunt_id=hunt_id,
        creator=result.creator,
        flow=result,
        labels=labels,
        state="Proposed",
        timestamp=now)

    for approver in approvers:
        users.send_notifications(
            current, approver, "HUNT_APPROVAL_REQUEST", dict(
                hunt_id=hunt_id,
                user=utils.get_current_username(current)))

    audit.log(current, "HuntProposal", hunt_id=hunt_id)

    return {}
Exemplo n.º 11
0
def launch_canned_flows(current, client_id, name):
    db = current.db
    row = db(db.canned_flows.name == name).select().first()
    if not row:
        raise ValueError("There is no canned flow with name '%s'" % name)

    also_upload_files = False
    flow_id = utils.new_flow_id()
    for action in row.flow.actions:
        if action.rekall_session.get("also_upload_files"):
            also_upload_files = True
        action.collection = dict(__type__="JSONCollection",
                                 location=dict(
                                     __type__="BlobUploader",
                                     base=html.URL(c="api",
                                                   f="control",
                                                   args=['upload'],
                                                   host=True),
                                     path_template=("collection/%s/{part}" %
                                                    flow_id),
                                 ))

    flow = agent.Flow.from_keywords(
        name=name,
        flow_id=flow_id,
        created_time=time.time(),
        ticket=dict(location=dict(
            __type__="HTTPLocation",
            base=utils.route_api('/control/ticket'),
            path_prefix=flow_id,
        )),
        actions=row.flow.actions,
    )

    if also_upload_files:
        flow.file_upload = dict(__type__="FileUploadLocation",
                                flow_id=flow_id,
                                base=html.URL(c="api",
                                              f='control/file_upload',
                                              host=True))

    db.flows.insert(
        flow_id=flow_id,
        client_id=client_id,
        status=agent.FlowStatus.from_keywords(timestamp=time.time(),
                                              client_id=client_id,
                                              flow_id=flow_id,
                                              status="Pending"),
        creator=utils.get_current_username(current),
        flow=flow,
        timestamp=flow.created_time.timestamp,
    )

    firebase.notify_client(client_id)

    audit.log(current,
              "FlowLaunchCanned",
              flow_id=flow_id,
              canned_flow=name,
              client_id=client_id)

    return {}
Exemplo n.º 12
0
def launch_plugin_flow(current, client_id, rekall_session, plugin, plugin_arg):
    """Launch the flow on the client."""
    db = current.db
    flow_id = utils.new_flow_id()
    spec = plugins.RekallAPI(current).get(plugin)
    if not spec:
        raise ValueError("Unknown plugin")

    # Validate both plugin args and session args.
    validate_plugin_args(plugin_arg, spec)
    validate_plugin_args(rekall_session, plugins.SessionAPI(current))

    flow = agent.Flow.from_keywords(
        flow_id=flow_id,
        created_time=time.time(),
        ticket=dict(location=dict(
            __type__="HTTPLocation",
            base=utils.route_api('/control/ticket'),
            path_prefix=flow_id,
        )),
        actions=[
            dict(__type__="PluginAction",
                 plugin=plugin,
                 args=plugin_arg,
                 rekall_session=rekall_session,
                 collection=dict(__type__="JSONCollection",
                                 location=dict(
                                     __type__="BlobUploader",
                                     base=html.URL(c="api",
                                                   f="control",
                                                   args=['upload'],
                                                   host=True),
                                     path_template=("collection/%s/{part}" %
                                                    flow_id),
                                 )))
        ])

    if rekall_session.get("also_upload_files"):
        flow.file_upload = dict(__type__="FileUploadLocation",
                                flow_id=flow_id,
                                base=html.URL(c="api",
                                              f='control/file_upload',
                                              host=True))

    db.flows.insert(
        flow_id=flow_id,
        client_id=client_id,
        status=agent.FlowStatus.from_keywords(timestamp=time.time(),
                                              client_id=client_id,
                                              flow_id=flow_id,
                                              status="Pending"),
        creator=utils.get_current_username(current),
        flow=flow,
        timestamp=flow.created_time.timestamp,
    )

    firebase.notify_client(client_id)

    audit.log(current,
              "FlowLaunchPlugin",
              flow_id=flow_id,
              plugin=plugin,
              client_id=client_id)

    return {}