This commit is contained in:
0
iris-web/source/app/blueprints/search/__init__.py
Normal file
0
iris-web/source/app/blueprints/search/__init__.py
Normal file
151
iris-web/source/app/blueprints/search/search_routes.py
Normal file
151
iris-web/source/app/blueprints/search/search_routes.py
Normal file
@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# IRIS Source Code
|
||||
# Copyright (C) 2021 - Airbus CyberSecurity (SAS)
|
||||
# ir@cyberactionlab.net
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 3 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
# IMPORTS ------------------------------------------------
|
||||
from flask import Blueprint
|
||||
from flask import redirect
|
||||
from flask import render_template
|
||||
from flask import request
|
||||
from flask import url_for
|
||||
from sqlalchemy import and_
|
||||
|
||||
from app.forms import SearchForm
|
||||
from app.iris_engine.utils.tracker import track_activity
|
||||
from app.models import Comments
|
||||
from app.models.authorization import Permissions
|
||||
from app.models.cases import Cases
|
||||
from app.models.models import Client
|
||||
from app.models.models import Ioc
|
||||
from app.models.models import IocLink
|
||||
from app.models.models import IocType
|
||||
from app.models.models import Notes
|
||||
from app.models.models import Tlp
|
||||
from app.util import ac_api_requires
|
||||
from app.util import ac_requires
|
||||
from app.util import response_success
|
||||
|
||||
search_blueprint = Blueprint('search',
|
||||
__name__,
|
||||
template_folder='templates')
|
||||
|
||||
|
||||
# CONTENT ------------------------------------------------
|
||||
@search_blueprint.route('/search', methods=['POST'])
|
||||
@ac_api_requires(Permissions.search_across_cases)
|
||||
def search_file_post(caseid: int):
|
||||
|
||||
jsdata = request.get_json()
|
||||
search_value = jsdata.get('search_value')
|
||||
search_type = jsdata.get('search_type')
|
||||
files = []
|
||||
search_condition = and_()
|
||||
|
||||
track_activity("started a global search for {} on {}".format(search_value, search_type))
|
||||
|
||||
# if not ac_flag_match_mask(session['permissions'], Permissions.search_across_all_cases.value):
|
||||
# user_search_limitations = ac_get_fast_user_cases_access(current_user.id)
|
||||
# if user_search_limitations:
|
||||
# search_condition = and_(Cases.case_id.in_(user_search_limitations))
|
||||
#
|
||||
# else:
|
||||
# return response_success("Results fetched", [])
|
||||
|
||||
if search_type == "ioc":
|
||||
res = Ioc.query.with_entities(
|
||||
Ioc.ioc_value.label('ioc_name'),
|
||||
Ioc.ioc_description.label('ioc_description'),
|
||||
Ioc.ioc_misp,
|
||||
IocType.type_name,
|
||||
Tlp.tlp_name,
|
||||
Tlp.tlp_bscolor,
|
||||
Cases.name.label('case_name'),
|
||||
Cases.case_id,
|
||||
Client.name.label('customer_name')
|
||||
).filter(
|
||||
and_(
|
||||
Ioc.ioc_value.like(search_value),
|
||||
IocLink.ioc_id == Ioc.ioc_id,
|
||||
IocLink.case_id == Cases.case_id,
|
||||
Client.client_id == Cases.client_id,
|
||||
Ioc.ioc_tlp_id == Tlp.tlp_id,
|
||||
search_condition
|
||||
)
|
||||
).join(Ioc.ioc_type).all()
|
||||
|
||||
files = [row._asdict() for row in res]
|
||||
|
||||
if search_type == "notes":
|
||||
|
||||
ns = []
|
||||
if search_value:
|
||||
search_value = "%{}%".format(search_value)
|
||||
ns = Notes.query.filter(
|
||||
Notes.note_content.like(search_value),
|
||||
Cases.client_id == Client.client_id,
|
||||
search_condition
|
||||
).with_entities(
|
||||
Notes.note_id,
|
||||
Notes.note_title,
|
||||
Cases.name.label('case_name'),
|
||||
Client.name.label('client_name'),
|
||||
Cases.case_id
|
||||
).join(
|
||||
Notes.case
|
||||
).order_by(
|
||||
Client.name
|
||||
).all()
|
||||
|
||||
ns = [row._asdict() for row in ns]
|
||||
|
||||
files = ns
|
||||
|
||||
if search_type == "comments":
|
||||
search_value = "%{}%".format(search_value)
|
||||
comments = Comments.query.filter(
|
||||
Comments.comment_text.like(search_value),
|
||||
Cases.client_id == Client.client_id,
|
||||
search_condition
|
||||
).with_entities(
|
||||
Comments.comment_id,
|
||||
Comments.comment_text,
|
||||
Cases.name.label('case_name'),
|
||||
Client.name.label('customer_name'),
|
||||
Cases.case_id
|
||||
).join(
|
||||
Comments.case,
|
||||
Cases.client
|
||||
).order_by(
|
||||
Client.name
|
||||
).all()
|
||||
|
||||
files = [row._asdict() for row in comments]
|
||||
|
||||
return response_success("Results fetched", files)
|
||||
|
||||
|
||||
@search_blueprint.route('/search', methods=['GET'])
|
||||
@ac_requires(Permissions.search_across_cases)
|
||||
def search_file_get(caseid, url_redir):
|
||||
if url_redir:
|
||||
return redirect(url_for('search.search_file_get', cid=caseid))
|
||||
|
||||
form = SearchForm(request.form)
|
||||
return render_template('search.html', form=form)
|
||||
|
163
iris-web/source/app/blueprints/search/templates/search.html
Normal file
163
iris-web/source/app/blueprints/search/templates/search.html
Normal file
@ -0,0 +1,163 @@
|
||||
{% extends "layouts/default.html" %}
|
||||
|
||||
{% block title %} Search {% endblock title %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link href="/static/assets/css/dataTables.buttons.min.css" rel="stylesheet">
|
||||
{% endblock stylesheets %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if current_user.is_authenticated %}
|
||||
<div class="page-inner">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">Search across cases</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="" id="form_search">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="input-group">
|
||||
{{ form.search_value(placeholder="Search term - You can use % as a wilcard. Search is context-free." , class="form-control", type="text") }}
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-sm btn-outline-success" id="submit_search">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label mr-3">Set to search within</label>
|
||||
<div class="selectgroup selectgroup-pills">
|
||||
<label class="selectgroup-item">
|
||||
<input type="radio" name="search_type" value="ioc" class="selectgroup-input" checked="">
|
||||
<span class="selectgroup-button">IOC</span>
|
||||
</label>
|
||||
<label class="selectgroup-item">
|
||||
<input type="radio" name="search_type" value="notes" class="selectgroup-input">
|
||||
<span class="selectgroup-button">Notes</span>
|
||||
</label>
|
||||
<label class="selectgroup-item">
|
||||
<input type="radio" name="search_type" value="comments" class="selectgroup-input">
|
||||
<span class="selectgroup-button">Comments</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="table-responsive" style="display: none;" id="search_table_wrapper">
|
||||
<div class="selectgroup">
|
||||
<span id="table_buttons"></span>
|
||||
</div>
|
||||
<table class="table display table table-striped table-hover" width="100%" cellspacing="0" id="file_search_table" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th>MD5</th>
|
||||
<th>Filename</th>
|
||||
<th>Path</th>
|
||||
<th>VT Score</th>
|
||||
<th>Case seen</th>
|
||||
<th>Seen count</th>
|
||||
<th>Flag</th>
|
||||
<th>Comment</th>
|
||||
<th>VT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>MD5</th>
|
||||
<th>Filename</th>
|
||||
<th>Path</th>
|
||||
<th>VT Score</th>
|
||||
<th>Case seen</th>
|
||||
<th>Seen count</th>
|
||||
<th>Flag</th>
|
||||
<th>Comment</th>
|
||||
<th>VT</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div class="table-responsive" style="display: none;" id="search_table_wrapper_1">
|
||||
<div class="selectgroup">
|
||||
<span id="table_buttons_1"></span>
|
||||
</div>
|
||||
<table class="table display table table-striped table-hover" width="100%" cellspacing="0" id="file_search_table_1" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Type</th>
|
||||
<th>Case</th>
|
||||
<th>Customer</th>
|
||||
<th>TLP</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Type</th>
|
||||
<th>Case</th>
|
||||
<th>Customer</th>
|
||||
<th>TLP</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div class="table-responsive" id="search_table_wrapper_2">
|
||||
<ul class="list-group list-group-bordered list " id="notes_msearch_list">
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="table-responsive" style="display: none;" id="search_table_wrapper_3">
|
||||
<div class="selectgroup">
|
||||
<span id="table_buttons_2"></span>
|
||||
</div>
|
||||
<table class="table display table table-striped table-hover" width="100%" cellspacing="0" id="comments_search_table" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#ID</th>
|
||||
<th>Comment text</th>
|
||||
<th>Case</th>
|
||||
<th>Customer</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>#ID</th>
|
||||
<th>Comment text</th>
|
||||
<th>Case</th>
|
||||
<th>Customer</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" tabindex="-1" role="dialog" id="modal_note_detail">
|
||||
<div class="modal-dialog modal-xxl modal-xl" role="document">
|
||||
<div class="modal-content" id="info_note_modal_content">
|
||||
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="/static/assets/js/plugin/datatables/dataTables.cellEdit.js"></script>
|
||||
<script src="/static/assets/js/plugin/datatables/dataTables.buttons.min.js"></script>
|
||||
<script src="/static/assets/js/plugin/datatables/buttons.html5.min.js"></script>
|
||||
<script src="/static/assets/js/plugin/datatables/buttons.print.min.js"></script>
|
||||
|
||||
<script src="/static/assets/js/plugin/ace/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="/static/assets/js/plugin/ace/src-noconflict/ext-language_tools.js" type="text/javascript"
|
||||
charset="utf-8"></script>
|
||||
|
||||
<script src="/static/assets/js/plugin/showdown/showdown.min.js"></script>
|
||||
<script src="/static/assets/js/iris/case.js"></script>
|
||||
<script src="/static/assets/js/iris/search.js"></script>
|
||||
{% endblock javascripts %}
|
Reference in New Issue
Block a user