Skip to content

Commit

Permalink
Add functionality to download Canarytoken incident history as JSON an…
Browse files Browse the repository at this point in the history
…d CSV file formats

Summary: Functionality has been added to the history page of Canarytokens, in order to allow the incident history to be downloaded in either JSON or CSV file formats.

Test Plan: Tested on localhost.

Reviewers: nick

Reviewed By: nick

Maniphest Tasks: T460

Differential Revision: http://phabricator.thinkst.com:9000/D611
  • Loading branch information
danielle-thinkst committed Aug 10, 2018
1 parent dde51f4 commit 58b24a9
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 3 deletions.
35 changes: 35 additions & 0 deletions httpd_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import tempfile
import hashlib
import os
from cStringIO import StringIO
import csv

env = Environment(loader=FileSystemLoader('templates'),
extensions=['jinja2.ext.loopcontrols'])
Expand Down Expand Up @@ -341,6 +343,39 @@ def render_GET(self, request):
text="[default]\naws_access_key={id}\naws_secret_access_key={k}"\
.format(id=canarydrop['aws_access_key_id'], k=canarydrop['aws_secret_access_key'])
return text
elif fmt == 'incidentlist_json':
request.setHeader("Content-Type", "text/plain")
request.setHeader("Content-Disposition",
'attachment; filename={token}_history.json'\
.format(token=token))
return simplejson.dumps(canarydrop['triggered_list'], indent=4)
elif fmt == 'incidentlist_csv':
request.setHeader("Content-Type", "text/plain")
request.setHeader("Content-Disposition",
'attachment; filename={token}_history.csv'\
.format(token=token))
csvOutput = StringIO()
incident_list = canarydrop['triggered_list']

writer = csv.writer(csvOutput)

details = []
for key in incident_list:
for element in incident_list[key].keys():
details.append(element)

headers = ["Timestamp"] + details
writer.writerow(headers)
items = []
for item in details:
for key in incident_list:
items.append(incident_list[key][item])

for key in incident_list:
data = [datetime.datetime.fromtimestamp(float(key)).strftime('%Y-%m-%d %H:%M:%S.%s')] + items
writer.writerow(data)

return csvOutput.getvalue()

except Exception as e:
log.err('Unexpected error in download: {err}'.format(err=e))
Expand Down
1 change: 0 additions & 1 deletion smtpd.tac
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ class SimpleRealm:
implements(IRealm)

def requestAvatar(self, avatarId, mind, *interfaces):
import pdb;pdb.set_trace()

if smtp.IMessageDelivery in interfaces:
return smtp.IMessageDelivery, CanaryMessageDelivery(), lambda: None
Expand Down
64 changes: 62 additions & 2 deletions templates/history.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ <h3>History for Canarytoken: <p class="token-length">{{canarydrop['canarytoken']
</div>
<div class="row content">
<div class="col-sm-6 incident-size">
<h4 style="text-align: center;">Incident Map</h4>
<div class="row" style="align-items: center;">
<div class="col-md 12">
<h4 style="text-align: center;">Incident Map</h4>
</div>
</div>
{% if API_KEY %}
<div class="row">
<div class="col-md-12"><div class="map" id="map"></div></div>
Expand All @@ -68,7 +72,21 @@ <h4 style="text-align: center;">Incident Map</h4>
</div>
<div class="col-sm-6 incident-size">
{% if (canarydrop['triggered_list']|length) > 0 %}
<h4 style="text-align: center;">Incident List</h4>

<div class="row" style="align-items: center;">
<h4 style="text-align: center;" class="col-md-9">Incident List</h4>
<div id="file_format" class="wrapper-dropdown form-control col-md-2" style="text-align: center;margin-bottom: 0;padding: 5px;" tabindex="1">
<span id="selected_file_format">
Export
</span>
<input name="file_format" type="hidden">
<ul id="file_format_dropdown" class="dropdown">
<li data-type="JSON" data-memo-placeholder="Download incident list as a (.json)"><a onClick="jsonDownload()"><span class="title">JSON File Format</span><div class="explanation">Download incident list as (.json)</div></a></li>
<li data-type="CSV" data-memo-placeholder="Download incident list as a (.csv)"><a onClick="csvDownload()"><span class="title">CSV File Format</span><div class="explanation">Download incident list as (.csv)</div></a></li>
</ul>
</div>
</div>

<!-- <h6 class="text-info" style="text-align: center;">Click to expand Incidents</h6> -->
{% else %}
<h4 style="text-align: center;">Incident List is Currently Empty</h4>
Expand Down Expand Up @@ -308,6 +326,14 @@ <h4 style="text-align: center;">Incident List is Currently Empty</h4>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="/resources/site.js"></script>
<script>

function jsonDownload() {
window.location = "/download?fmt=incidentlist_json&token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}";
}
function csvDownload() {
window.location = "/download?fmt=incidentlist_csv&token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}";
}

var green_icon = 'http://maps.google.com/mapfiles/ms/icons/green-dot.png';
var red_icon = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png'

Expand Down Expand Up @@ -423,6 +449,40 @@ <h4 style="text-align: center;">Incident List is Currently Empty</h4>
$('.expand').click(function(){
$(this).find('.incident-item-details').slideToggle('slow');
});


function DropDown(el, click_cb) {
this.dd = el;
this.click_cb = click_cb;
this.initEvents();
}
DropDown.prototype = {
initEvents : function() {
var obj = this;

obj.dd.on('click', function(event){
$(this).toggleClass('active');
if ($(event.target).parents().hasClass('file_format_dropdown') && obj.click_cb) {
obj.click_cb(event);
}
event.stopPropagation();
});
}
}
$(function() {
/* init dropdown menu */
var dd = new DropDown( $('#file_format'),
function(event) {
var list_item = $(event.target).parents('li');
$('#file_format_dropdown').data('selected', list_item.data('file_format'))
$('#selected_file_format').text(list_item.find('span.title').text());
});
});

$(document).click(function() {
$('.wrapper-dropdown').removeClass('active');
});

</script>
{% if API_KEY %}
<script src="https://maps.googleapis.com/maps/api/js?key={{API_KEY}}&callback=initMap" async defer></script>
Expand Down

0 comments on commit 58b24a9

Please sign in to comment.