Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Signature TLO, Take Advantage of the PATCH API #675

Merged
merged 1 commit into from
Dec 30, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion crits/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ def obj_update(self, bundle, **kwargs):
import crits.objects.handlers as objh
import crits.relationships.handlers as relh
import crits.services.handlers as servh
import crits.signatures.handlers as sigh
import crits.indicators.handlers as indh

actions = {
Expand Down Expand Up @@ -613,7 +614,14 @@ def obj_update(self, bundle, **kwargs):
'PCAP': {},
'RawData': {},
'Sample': {},
'Signature': {},
'Signature': {
'update_dependency': sigh.update_dependency,
'update_min_version': sigh.update_min_version,
'update_max_version': sigh.update_max_version,
'update_signature_data': sigh.update_signature_data,
'update_signature_type': sigh.update_signature_type,
'update_title': sigh.update_title
},
'Target': {},
}

Expand Down
147 changes: 120 additions & 27 deletions crits/signatures/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,27 +413,41 @@ def handle_signature_file(data, source_name, user=None,
return status


def update_signature_type(_id, data_type, analyst):
def update_signature_type(type_, id_, data_type, user, **kwargs):
"""
Update the Signature data type.

:param _id: ObjectId of the Signature to update.
:type _id: str
:param type_: The CRITs type of the top-level object.
:type type_: str
:param id_: ObjectId of the Signature to update.
:type id_: str
:param data_type: The data type to set.
:type data_type: str
:param analyst: The user updating the data type.
:type analyst: str
:param user: The user updating the data type.
:type user: str
:returns: dict with keys "success" (boolean) and "message" (str) if failed.
"""

signature = Signature.objects(id=_id).first()
klass = class_from_type(type_)
if not klass:
return {'success': False, 'message': 'Could not find object.'}

if hasattr(klass, 'source'):
sources = user_sources(user)
obj = klass.objects(id=id_, source__name__in=sources).first()
else:
obj = klass.objects(id=id_).first()
if not obj:
return {'success': False, 'message': 'Could not find object.'}

signature = Signature.objects(id=id_).first()
data_type = SignatureType.objects(name=data_type).first()
if not data_type:
return None
else:
signature.data_type = data_type.name
try:
signature.save(username=analyst)
signature.save(username=user)
return {'success': True}
except ValidationError, e:
return {'success': False, 'message': str(e)}
Expand Down Expand Up @@ -533,18 +547,20 @@ def add_new_signature_type(data_type, analyst):
return False


def update_dependency(type_, id_, dep, analyst):
def update_dependency(type_, id_, dep, user, append=False, **kwargs):
"""
Change the min version of the data tool
Change the dependencies needed for a signature

:param type_: The CRITs type of the top-level object.
:type type_: str
:param id_: The ObjectId to search for.
:type id_: str
:param data_type_dependency: The new list of dependency
:param data_type_dependency: The new list of dependencies
:type data_type_dependency: list
:param analyst: The user setting the description.
:type analyst: str
:param user: The user setting the dependency.
:type user: str
:param append: Should be appended to dependency list?
:type append: boolean
:returns: dict with keys "success" (boolean) and "message" (str)
"""

Expand All @@ -554,7 +570,7 @@ def update_dependency(type_, id_, dep, analyst):
return {'success': False, 'message': 'Could not find object.'}

if hasattr(klass, 'source'):
sources = user_sources(analyst)
sources = user_sources(user)
obj = klass.objects(id=id_, source__name__in=sources).first()
else:
obj = klass.objects(id=id_).first()
Expand All @@ -567,22 +583,23 @@ def update_dependency(type_, id_, dep, analyst):
data_type_dependency = h.unescape(dep)
try:
deps = data_type_dependency.split(',')
del obj.data_type_dependency[:]

if append is False:
del obj.data_type_dependency[:]
for item in deps:
item = item.strip()
item = str(item)
if item:
add_new_signature_dependency(item, analyst)
add_new_signature_dependency(item, user)
obj.data_type_dependency.append(item)

obj.save(username=analyst)
obj.save(username=user)
return {'success': True, 'message': "Data type dependency set."}
except ValidationError, e:
return {'success': False, 'message': e}


def update_min_version(type_, id_, data_type_min_version, analyst):

def update_min_version(type_, id_, data_type_min_version, user, **kwargs):
"""
Change the min version of the data tool

Expand All @@ -592,8 +609,8 @@ def update_min_version(type_, id_, data_type_min_version, analyst):
:type id_: str
:param data_type_min_version: The new min version to use.
:type data_type_min_version: str
:param analyst: The user setting the description.
:type analyst: str
:param user: The user setting the description.
:type user: str
:returns: dict with keys "success" (boolean) and "message" (str)
"""

Expand All @@ -602,7 +619,7 @@ def update_min_version(type_, id_, data_type_min_version, analyst):
return {'success': False, 'message': 'Could not find object.'}

if hasattr(klass, 'source'):
sources = user_sources(analyst)
sources = user_sources(user)
obj = klass.objects(id=id_, source__name__in=sources).first()
else:
obj = klass.objects(id=id_).first()
Expand All @@ -615,13 +632,13 @@ def update_min_version(type_, id_, data_type_min_version, analyst):
data_type_min_version = h.unescape(data_type_min_version)
try:
obj.data_type_min_version = data_type_min_version
obj.save(username=analyst)
obj.save(username=user)
return {'success': True, 'message': "Data type min version set."}
except ValidationError, e:
return {'success': False, 'message': e}


def update_max_version(type_, id_, data_type_max_version, analyst):
def update_max_version(type_, id_, data_type_max_version, user, **kwargs):
"""
Change the max version of the data tool

Expand All @@ -631,8 +648,8 @@ def update_max_version(type_, id_, data_type_max_version, analyst):
:type id_: str
:param data_type_max_version: The new max version to use.
:type data_type_max_version: str
:param analyst: The user setting the description.
:type analyst: str
:param user: The user setting the description.
:type user: str
:returns: dict with keys "success" (boolean) and "message" (str)
"""

Expand All @@ -641,7 +658,7 @@ def update_max_version(type_, id_, data_type_max_version, analyst):
return {'success': False, 'message': 'Could not find object.'}

if hasattr(klass, 'source'):
sources = user_sources(analyst)
sources = user_sources(user)
obj = klass.objects(id=id_, source__name__in=sources).first()
else:
obj = klass.objects(id=id_).first()
Expand All @@ -654,7 +671,7 @@ def update_max_version(type_, id_, data_type_max_version, analyst):
data_type_max_version = h.unescape(data_type_max_version)
try:
obj.data_type_max_version = data_type_max_version
obj.save(username=analyst)
obj.save(username=user)
return {'success': True, 'message': "Data type max version set."}
except ValidationError, e:
return {'success': False, 'message': e}
Expand All @@ -672,3 +689,79 @@ def get_dependency_autocomplete(term):
deps = [b.name for b in results]
return HttpResponse(json.dumps(deps, default=json_handler),
content_type='application/json')

def update_signature_data(type_, id_, data, user, **kwargs):
"""
Change signature data for the current version

:param type_: The CRITs type of the top-level object.
:type type_: str
:param id_: The ObjectId to search for.
:type id_: str
:param data: The new signature value to use.
:type data: str
:param user: The user setting the data value.
:type user: str
:returns: dict with keys "success" (boolean) and "message" (str)
"""

klass = class_from_type(type_)
if not klass:
return {'success': False, 'message': 'Could not find object.'}

if hasattr(klass, 'source'):
sources = user_sources(user)
obj = klass.objects(id=id_, source__name__in=sources).first()
else:
obj = klass.objects(id=id_).first()
if not obj:
return {'success': False, 'message': 'Could not find object.'}

# Have to unescape the submitted data. Use unescape() to escape
# < and friends. Use urllib2.unquote() to escape %3C and friends.
h = HTMLParser.HTMLParser()
data = h.unescape(data)
try:
obj.data = data
obj.save(username=user)
return {'success': True, 'message': "Signature value updated."}
except ValidationError, e:
return {'success': False, 'message': e}

def update_title(type_, id_, title, user, **kwargs):
"""
Change signature data for the current version

:param type_: The CRITs type of the top-level object.
:type type_: str
:param id_: The ObjectId to search for.
:type id_: str
:param title: The new signature title to use.
:type title: str
:param user: The user setting the data value.
:type user: str
:returns: dict with keys "success" (boolean) and "message" (str)
"""

klass = class_from_type(type_)
if not klass:
return {'success': False, 'message': 'Could not find object.'}

if hasattr(klass, 'source'):
sources = user_sources(user)
obj = klass.objects(id=id_, source__name__in=sources).first()
else:
obj = klass.objects(id=id_).first()
if not obj:
return {'success': False, 'message': 'Could not find object.'}

# Have to unescape the submitted data. Use unescape() to escape
# < and friends. Use urllib2.unquote() to escape %3C and friends.
h = HTMLParser.HTMLParser()
data = h.unescape(title)
try:
obj.title = data
obj.save(username=title)
return {'success': True, 'message': "Signature title updated."}
except ValidationError, e:
return {'success': False, 'message': e}
1 change: 1 addition & 0 deletions crits/signatures/static/js/signatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ $(document).ready(function() {
return function(value, settings, elem) {
var data = {
data_type: value,
type: subscription_type,
};
$.ajax({
type: "POST",
Expand Down
2 changes: 1 addition & 1 deletion crits/signatures/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
(r'^details/(?P<_id>\w+)/$', 'signature_detail'),
(r'^details_by_link/(?P<link>.+)/$', 'details_by_link'),
(r'^get_versions/(?P<_id>\w+)/$', 'get_signature_versions'),
(r'^set_signature_type/(?P<_id>\w+)/$', 'set_signature_type'),
(r'^set_signature_type/(?P<id_>\w+)/$', 'set_signature_type'),
(r'^update_data_type_min_version/$', 'update_data_type_min_version'),
(r'^update_data_type_max_version/$', 'update_data_type_max_version'),
(r'^update_data_type_dependency/$', 'update_data_type_dependency'),
Expand Down
18 changes: 7 additions & 11 deletions crits/signatures/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,23 @@ def signatures_listing(request,option=None):
return generate_signature_jtable(request, option)

@user_passes_test(user_can_view_data)
def set_signature_type(request, _id):
def set_signature_type(request, id_):
"""
Set the Signature datatype. Should be an AJAX POST.

:param request: Django request object (Required)
:type request: :class:`django.http.HttpRequest`
:param _id: The ObjectId of the Signature.
:type _id: str
:param id_: The ObjectId of the Signature.
:type id_: str
:returns: :class:`django.http.HttpResponse`
"""

if request.method == 'POST':
data_type = request.POST['data_type']
type_ = request.POST['type']
analyst = request.user.username
return HttpResponse(json.dumps(update_signature_type(_id,
return HttpResponse(json.dumps(update_signature_type(type_,
id_,
data_type,
analyst)),
mimetype="application/json")
Expand Down Expand Up @@ -202,30 +204,24 @@ def upload_signature(request, link_id=None):
@user_passes_test(user_can_view_data)
def update_data_type_dependency(request):
"""
Update the dependency listr in the signature.
Update the dependency list in the signature.

:param request: Django request.
:type request: :class:`django.http.HttpRequest`
:returns: :class:`django.http.HttpResponse`
"""

if request.method == "POST" and request.is_ajax():

type_ = request.POST['type']

id_ = request.POST['id']

data_deps = request.POST['data_type_dependency']

analyst = request.user.username

return HttpResponse(json.dumps(update_dependency(type_,
id_,
data_deps,
analyst)),
mimetype="application/json")
else:

return render_to_response("error.html",
{"error" : 'Expected AJAX POST.'},
RequestContext(request))
Expand Down
Loading