Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Pavel.Valach/warden
1 result
Show changes
Showing
with 2795 additions and 1994 deletions
/*
*
* -*- coding: utf-8 -*-
*
* warden-map.css
*
* Copyright (C) 2016 Cesnet z.s.p.o
* Use of this source is governed by a 3-clause BSD-style license, see LICENSE file.
*
*/
body {
font-family: 'Oswald', sans-serif;
background: #00253D;
border: 0px;
padding: 0px;
margin: 0px;
}
h2 {
color: #0062a2;
}
.hoverinfo {
font-family: 'Oswald', sans-serif;
}
#country {
color: #0062a2; /* Cesnet blue */
font-weight: bold;
}
table {
text-align: left;
margin: 0;
padding: 0;
font-size: 12px;
}
table th {
color: #0062a2; /* Cesnet blue */
padding: 0;
}
table td {
color: #4b4d4a; /* Greenish gray */
padding: 0;
}
#container {
overflow: hidden;
/* border: 2px solid #0062a2;
border: 0px;
padding: 0px;
margin: 0px;
border-radius: 5px;*/
position: relative;
/* width: 1280px;
height: 720px;*/
max-width: 100%;
max-height: 100%
width: 100%;
height: 100vh;*/
}
.zoom-button {
width: 40px;
height: 40px;
border-radius: 5px;
border: none;
background: #dcdcda;
font-size: 23px;
font-weight: bold;
color: white;
cursor: pointer;
}
.zoom-button:hover {
background-color: #0062a2;
}
#zoom-info {
display: inline-block;
padding: 10px;
color: #0062a2;
}
#warden-logo {
position: absolute;
top: 30px;
left: 30px;
background: white;
padding: 10px;
border-radius: 10px;
width: 240px;
height: 92px;
text-align: center;
}
#cesnet-logo {
position: absolute;
top: 30px;
right: 30px;
background: white;
padding: 10px;
border-radius: 10px;
width: 240px;
height: 92px;
text-align: center;
}
#legend-box {
position: absolute;
bottom: 30px;
left: 30px;
background-color: rgba(0,0,0,0.3);
color: white;
padding: 10px;
border-radius: 10px;
/*width: 240px;
height: 92px;
text-align: center;*/
}
#heading {
position: absolute;
top: 30px;
left: 50%;
width: 40em;
height: 92px;
margin-left: -20em;
font-size: xx-large;
color: white;
text-align: center;
vertical-align: middle;
line-height: 92px;
}
/*
*
* -*- coding: utf-8 -*-
*
* warden-map.js
*
* Copyright (C) 2016 Cesnet z.s.p.o
* Use of this source is governed by a 3-clause BSD-style license, see LICENSE file.
*
*/
// NOTE: Change path in a function d3.json() if you separate backend and frontend!
// Zooming functionality is based on WunderBart's implementation
// Please see following links:
// https://github.com/wunderbart
// https://jsfiddle.net/wunderbart/Lom3b0gb/
function Zoom(args) {
$.extend(this, {
$buttons: $(".zoom-button"),
$info: $("#zoom-info"),
scale: { max: 50, currentShift: 0 },
$container: args.$container,
datamap: args.datamap
});
this.init();
}
Zoom.prototype.init = function() {
var paths = this.datamap.svg.selectAll("path"),
subunits = this.datamap.svg.selectAll(".datamaps-subunit");
// preserve stroke thickness
paths.style("vector-effect", "non-scaling-stroke");
// disable click on drag end
subunits.call(
d3.behavior.drag().on("dragend", function() {
d3.event.sourceEvent.stopPropagation();
})
);
this.scale.set = this._getScalesArray();
this.d3Zoom = d3.behavior.zoom().scaleExtent([ 1, this.scale.max ]);
this._displayPercentage(1);
this.listen();
};
Zoom.prototype.listen = function() {
this.$buttons.off("click").on("click", this._handleClick.bind(this));
this.datamap.svg
.call(this.d3Zoom.on("zoom", this._handleScroll.bind(this)))
.on("dblclick.zoom", null); // disable zoom on double-click
};
Zoom.prototype.reset = function() {
this._shift("reset");
};
Zoom.prototype._handleScroll = function() {
var translate = d3.event.translate,
scale = d3.event.scale,
limited = this._bound(translate, scale);
this.scrolled = true;
this._update(limited.translate, limited.scale);
};
Zoom.prototype._handleClick = function(event) {
var direction = $(event.target).data("zoom");
this._shift(direction);
};
Zoom.prototype._shift = function(direction) {
var center = [ this.$container.width() / 2, this.$container.height() / 2 ],
translate = this.d3Zoom.translate(), translate0 = [], l = [],
view = {
x: translate[0],
y: translate[1],
k: this.d3Zoom.scale()
}, bounded;
translate0 = [
(center[0] - view.x) / view.k,
(center[1] - view.y) / view.k
];
if (direction == "reset") {
view.k = 1;
this.scrolled = true;
} else {
view.k = this._getNextScale(direction);
}
l = [ translate0[0] * view.k + view.x, translate0[1] * view.k + view.y ];
view.x += center[0] - l[0];
view.y += center[1] - l[1];
bounded = this._bound([ view.x, view.y ], view.k);
this._animate(bounded.translate, bounded.scale);
};
Zoom.prototype._bound = function(translate, scale) {
var width = this.$container.width(),
height = this.$container.height();
translate[0] = Math.min(
(width / height) * (scale - 1),
Math.max( width * (1 - scale), translate[0] )
);
translate[1] = Math.min(0, Math.max(height * (1 - scale), translate[1]));
return { translate: translate, scale: scale };
};
Zoom.prototype._update = function(translate, scale) {
this.d3Zoom
.translate(translate)
.scale(scale);
this.datamap.svg.selectAll("g")
.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
this._displayPercentage(scale);
};
Zoom.prototype._animate = function(translate, scale) {
var _this = this,
d3Zoom = this.d3Zoom;
d3.transition().duration(350).tween("zoom", function() {
var iTranslate = d3.interpolate(d3Zoom.translate(), translate),
iScale = d3.interpolate(d3Zoom.scale(), scale);
return function(t) {
_this._update(iTranslate(t), iScale(t));
};
});
};
Zoom.prototype._displayPercentage = function(scale) {
var value;
value = Math.round(Math.log(scale) / Math.log(this.scale.max) * 100);
this.$info.text(value + "%");
};
Zoom.prototype._getScalesArray = function() {
var array = [],
scaleMaxLog = Math.log(this.scale.max);
for (var i = 0; i <= 10; i++) {
array.push(Math.pow(Math.E, 0.1 * i * scaleMaxLog));
}
return array;
};
Zoom.prototype._getNextScale = function(direction) {
var scaleSet = this.scale.set,
currentScale = this.d3Zoom.scale(),
lastShift = scaleSet.length - 1,
shift, temp = [];
if (this.scrolled) {
for (shift = 0; shift <= lastShift; shift++) {
temp.push(Math.abs(scaleSet[shift] - currentScale));
}
shift = temp.indexOf(Math.min.apply(null, temp));
if (currentScale >= scaleSet[shift] && shift < lastShift) {
shift++;
}
if (direction == "out" && shift > 0) {
shift--;
}
this.scrolled = false;
} else {
shift = this.scale.currentShift;
if (direction == "out") {
shift > 0 && shift--;
} else {
shift < lastShift && shift++;
}
}
this.scale.currentShift = shift;
return scaleSet[shift];
};
function defaults(obj) {
Array.prototype.slice.call(arguments, 1).forEach(function(source) {
if (source) {
for (var prop in source) {
// Deep copy if property not set
if (obj[prop] == null) {
if (typeof source[prop] == 'function') {
obj[prop] = source[prop];
}
else {
obj[prop] = JSON.parse(JSON.stringify(source[prop]));
}
}
}
}
});
return obj;
}
function val( datumValue, optionsValue, context ) {
if ( typeof context === 'undefined' ) {
context = optionsValue;
optionsValues = undefined;
}
var value = typeof datumValue !== 'undefined' ? datumValue : optionsValue;
if (typeof value === 'undefined') {
return null;
}
if ( typeof value === 'function' ) {
var fnContext = [context];
if ( context.geography ) {
fnContext = [context.geography, context.data];
}
return value.apply(null, fnContext);
}
else {
return value;
}
}
var cat_color = {
"Abusive": "MediumPurple",
"Malware": "Red",
"Recon": "LightSlateGray",
"Attempt": "GhostWhite",
"Intrusion": "DarkTurquoise",
"Availability": "HotPink",
"Information": "PaleTurquoise",
"Fraud": "Yellow",
"Vulnerable": "DarkGoldenRod",
"Anomaly": "Brown",
"Other": "Green"
}
var cat_desc = {
"Abusive": "spam",
"Malware": "virus, worm, trojan, malware",
"Recon": "scanning, sniffing",
"Attempt": "bruteforce, exploitation attempt",
"Intrusion": "botnet, successful exploit",
"Availability": "(D)DOS",
"Information": "wiretapping, spoofing, hijacking",
"Fraud": "phishing, scam",
"Vulnerable": "open for abuse",
"Anomaly": "unusual traffic",
"Other": "unknown/unidentified"
}
function handleArcs (layer, data, options) {
var self = this,
svg = this.svg;
if ( !data || (data && !data.slice) ) {
throw "Datamaps Error - arcs must be an array";
}
// For some reason arc options were put in an `options` object instead of the parent arc
// I don't like this, so to match bubbles and other plugins I'm moving it
// This is to keep backwards compatability
for ( var i = 0; i < data.length; i++ ) {
data[i] = defaults(data[i], data[i].options);
delete data[i].options;
}
if ( typeof options === "undefined" ) {
options = defaultOptions.arcConfig;
}
var arcs = layer.selectAll('path.datamaps-arc').data( data, JSON.stringify );
var path = d3.geo.path()
.projection(self.projection);
arcs
.enter()
.append('svg:path')
.attr('class', 'datamaps-arc')
.style('stroke-linecap', 'round')
.style('stroke', function(datum) {
/* return val(datum.strokeColor, options.strokeColor, datum);*/
for (cat in cat_color) {
if (datum.event.startsWith(cat)) {
return cat_color[cat];
}
}
return "Green";
})
.style('fill', 'none')
.style('stroke-width', function(datum) {
return val(datum.strokeWidth, options.strokeWidth, datum);
})
.attr('d', function(datum) {
var originXY, destXY;
originXY = self.latLngToXY(val(datum.origin.latitude, datum), val(datum.origin.longitude, datum))
destXY = self.latLngToXY(val(datum.destination.latitude, datum), val(datum.destination.longitude, datum));
var midXY = [ (originXY[0] + destXY[0]) / 2, (originXY[1] + destXY[1]) / 2];
if (options.greatArc) {
// TODO: Move this to inside `if` clause when setting attr `d`
var greatArc = d3.geo.greatArc()
.source(function(d) { return [val(d.origin.longitude, d), val(d.origin.latitude, d)]; })
.target(function(d) { return [val(d.destination.longitude, d), val(d.destination.latitude, d)]; });
return path(greatArc(datum))
}
var sharpness = val(datum.arcSharpness, options.arcSharpness, datum);
return "M" + originXY[0] + ',' + originXY[1] + "S" + (midXY[0] + (50 * sharpness)) + "," + (midXY[1] - (75 * sharpness)) + "," + destXY[0] + "," + destXY[1];
})
.attr('data-info', function(datum) {
return JSON.stringify(datum);
})
.on('mouseover', function ( datum ) {
var $this = d3.select(this);
if (options.popupOnHover) {
self.updatePopup($this, datum, options, svg);
}
})
.on('mouseout', function ( datum ) {
var $this = d3.select(this);
d3.selectAll('.datamaps-hoverover').style('display', 'none');
})
.transition()
.style('fill', function(datum, i) {
/*
Thank you Jake Archibald, this is awesome.
Source: http://jakearchibald.com/2013/animated-line-drawing-svg/
*/
var length = this.getTotalLength();
this.style.transition = this.style.WebkitTransition = 'none';
this.style.strokeDasharray = length + ' ' + length;
this.style.strokeDashoffset = length;
this.getBoundingClientRect();
this.style.transition = this.style.WebkitTransition = 'stroke-dashoffset ' + val(datum.animationSpeed, options.animationSpeed, datum) + 'ms ' + datum.delay*1000 + 'ms ease-out';
this.style.strokeDashoffset = '0';
return 'none';
});
arcs.exit()
.transition()
.duration(1000)
.style('opacity', 0)
.remove();
}
var main_data = [];
var prev_data = 0;
// Configuration of datamap canvas
// Futher reading can be found at https://datamaps.github.io/
function Datamap() {
this.$container = $("#container");
instance = this.instance = new Datamaps({
scope: 'world',
element: this.$container.get(0),
done: this._handleMapReady.bind(this),
projection: 'mercator',
fills: {
/*defaultFill: '#454545'*/
defaultFill: 'black'
},
geographyConfig: {
hideAntarctica: true,
borderColor: '#0062a2',
highlightFillColor: '#4b4d4a',
highlightBorderColor: '#fdfdfd',
popupOnHover: true,
popupTemplate: function(geography, data) {
return '<div class="hoverinfo" id="country">' + geography.properties.name + '</div>';
},
},
ph_arcConfig: {
strokeColor: '#0062a2',
strokeWidth: 2,
arcSharpness: 2, /* 5 */
animationSpeed: 3000, // Milliseconds
popupOnHover: true,
// Case with latitude and longitude
popupTemplate: function(geography, data) {
if ( ( data.origin && data.destination ) && data.origin.latitude && data.origin.longitude && data.destination.latitude && data.destination.longitude ) {
// Content of info table
str = '<div class="hoverinfo"><table id="event"><tr><th>Warden Event</th></tr><tr><td>Type</td><td>'+ JSON.stringify(data.event) +'</td></tr><tr><td>Detect Time</td><td>'+ JSON.stringify(data.time) +'</td></tr><tr><th>Event origin</th></tr><tr><td>IP</td><td>' + JSON.stringify(data.origin.ip) + '</td></tr><tr><td>City & Country</td><td>' + JSON.stringify(data.origin.city) + ',&nbsp;' + JSON.stringify(data.origin.country_name) + '</td></tr><tr><td>GPS</td><td>' + JSON.stringify(data.origin.latitude) + ',&nbsp;' + JSON.stringify(data.origin.longitude) + '</td></tr><tr><th>Event Destination</th></tr><tr><td>IP</td><td>' + JSON.stringify(data.destination.ip) + '</td></tr><tr><td>City & Country</td><td>' + JSON.stringify(data.destination.city) + ',&nbsp;' + JSON.stringify(data.destination.country_name) + '</td></tr><tr><td>GPS</td><td>' + JSON.stringify(data.destination.latitude) + ',&nbsp;' + JSON.stringify(data.destination.longitude) + '</td></tr></table></div>';
return str.replace(/&quot;/g,"");
}
// Missing information
else {
return '';
}
}
}
});
legend_data = d3.select("#legend")
.selectAll("li")
.data(Object.keys(cat_color).sort())
.enter()
.append("li")
.append("span")
.style("color", function(datum) { return cat_color[datum]})
.text(function(datum) { return datum; })
.append("span")
.text(function(datum) { return "" + cat_desc[datum]})
.style("color", "white");
instance.addPlugin('ph_arc', handleArcs);
setInterval(function(){
d3.json("./warden-map.json", function(error, data) {
if (data) {
var cur_data = data.pop()
var cur_time = new Date().getTime();
if (cur_data != prev_data) {
prev_data = cur_data;
for (var i=0; i<data.length; i++) {
data[i].arrivalTime = cur_time;
data[i].delay = i/data.length;
}
main_data = main_data.concat(data);
}
}
var trimmed_data = [];
for (var i=0; i<main_data.length; i++) {
if (main_data[i].arrivalTime + 3500 > cur_time) {
trimmed_data.push(main_data[i]);
}
}
main_data = trimmed_data;
trimmed_data = cur_time = cur_data = error = data = null;
instance.ph_arc(main_data);
});
}, 1000);
};
Datamap.prototype._handleMapReady = function(datamap) {
this.zoom = new Zoom({
$container: this.$container,
datamap: datamap
});
}
<!-- -->
<!-- -->
<!-- -*- coding: utf-8 -*- -->
<!-- -->
<!-- warden-map.html -->
<!-- -->
<!-- Copyright (C) 2016 Cesnet z.s.p.o -->
<!-- Use of this source is governed by a 3-clause BSD-style license, see LICENSE file. -->
<!-- -->
<!-- -->
<!DOCTYPE html>
<meta name="robots" content="noindex">
<meta charset="utf-8">
<link href='https://fonts.googleapis.com/css?family=Oswald&amp;subset=latin,latin-ext' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="./css/warden-map.css"/>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="./js/datamaps.world.min.js"></script>
<script src="./js/warden-map.js"></script>
<!--
<h2>Warden Map</h2>
<div id="tools">
<button class="zoom-button" data-zoom="reset">&#x2302</button>
<button class="zoom-button" data-zoom="out">-</button>
<button class="zoom-button" data-zoom="in">+</button>
<div id="zoom-info"></div>
</div>
-->
<div id="container"></div>
<div id="heading">Attacks, detected in CESNET network<br/>
SABU - Sharing and Analysis of Security Events
</div>
<div id="legend-box">
<p><b>Reported to Warden right <i>now</i>.</b></p>
<ul id="legend"></ul>
</div>
<!-- Draw datamap into id="container" -->
<script>new Datamap();</script>
</body>
</html>
{
"url": "https://midas.civ.zcu.cz:8888/warden3",
"certfile": "kostik.zcu.cz-cert.pem",
"keyfile": "kostik.zcu.cz-key.pem",
"cafile": "Warden_CA-cacert.pem",
"timeout": 60,
"recv_events_limit": 6000,
"errlog": {"level": "debug"},
"filelog": {"file": "warden_client.log", "level": "warning"},
#"syslog": {"socket": "/dev/log", "facility": "local7", "level": "warning"},
"idstore": "warden_client.id",
"name": "warden_client_kostik",
"secret": "Phaipe5ush7p"
}
This diff is collapsed.
-- phpMyAdmin SQL Dump
-- version 3.4.11.1deb2+deb7u1
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Dec 04, 2014 at 02:54 PM
-- Server version: 5.5.38
-- PHP Version: 5.4.4-14+deb7u14
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Database: `warden3`
--
-- --------------------------------------------------------
--
-- Table structure for table `categories`
--
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL,
`category` varchar(64) NOT NULL,
`subcategory` varchar(64) DEFAULT NULL,
`cat_subcat` varchar(129) NOT NULL,
KEY `cat_sub` (`cat_subcat`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
--
-- Dumping data for table `categories`
--
INSERT INTO `categories` (`id`, `category`, `subcategory`, `cat_subcat`) VALUES
(100, 'Abusive', NULL, 'Abusive'),
(101, 'Abusive', 'Spam', 'Abusive.Spam'),
(102, 'Abusive', 'Harassment', 'Abusive.Harassment'),
(103, 'Abusive', 'Child', 'Abusive.Child'),
(104, 'Abusive', 'Sexual', 'Abusive.Sexual'),
(105, 'Abusive', 'Violence', 'Abusive.Violence'),
(200, 'Malware', NULL, 'Malware'),
(201, 'Malware', 'Virus', 'Malware.Virus'),
(202, 'Malware', 'Worm', 'Malware.Worm'),
(203, 'Malware', 'Trojan', 'Malware.Trojan'),
(204, 'Malware', 'Spyware', 'Malware.Spyware'),
(205, 'Malware', 'Dialer', 'Malware.Dialer'),
(206, 'Malware', 'Rootkit', 'Malware.Rootkit'),
(300, 'Recon', NULL, 'Recon'),
(301, 'Recon', 'Scanning', 'Recon.Scanning'),
(302, 'Recon', 'Sniffing', 'Recon.Sniffing'),
(303, 'Recon', 'SocialEngineering', 'Recon.SocialEngineering'),
(304, 'Recon', 'Searching', 'Recon.Searching'),
(400, 'Attempt', NULL, 'Attempt'),
(401, 'Attempt', 'Exploit', 'Attempt.Exploit'),
(402, 'Attempt', 'Login', 'Attempt.Login'),
(403, 'Attempt', 'NewSignature', 'Attempt.NewSignature'),
(500, 'Intrusion', NULL, 'Intrusion'),
(501, 'Intrusion', 'AdminCompromise', 'Intrusion.AdminCompromise'),
(502, 'Intrusion', 'UserCompromise', 'Intrusion.UserCompromise'),
(503, 'Intrusion', 'AppCompromise', 'Intrusion.AppCompromise'),
(504, 'Intrusion', 'Botnet', 'Intrusion.Botnet'),
(600, 'Availability', NULL, 'Availability'),
(601, 'Availability', 'DoS', 'Availability.DoS'),
(602, 'Availability', 'DDoS', 'Availability.DDoS'),
(603, 'Availability', 'Sabotage', 'Availability.Sabotage'),
(604, 'Availability', 'Outage', 'Availability.Outage'),
(700, 'Information', NULL, 'Information'),
(701, 'Information', 'UnauthorizedAccess', 'Information.UnauthorizedAccess'),
(702, 'Information', 'UnauthorizedModification', 'Information.UnauthorizedModification'),
(800, 'Fraud', NULL, 'Fraud'),
(801, 'Fraud', 'UnauthorizedUsage', 'Fraud.UnauthorizedUsage'),
(802, 'Fraud', 'Copyright', 'Fraud.Copyright'),
(803, 'Fraud', 'Masquerade', 'Fraud.Masquerade'),
(804, 'Fraud', 'Phishing', 'Fraud.Phishing'),
(805, 'Fraud', 'Scam', 'Fraud.Scam'),
(900, 'Vulnerable', NULL, 'Vulnerable'),
(901, 'Vulnerable', 'Open', 'Vulnerable.Open'),
(1000, 'Anomaly', NULL, 'Anomaly'),
(1001, 'Anomaly', 'Traffic', 'Anomaly.Traffic'),
(1002, 'Anomaly', 'Connection', 'Anomaly.Connection'),
(1003, 'Anomaly', 'Protocol', 'Anomaly.Protocol'),
(1004, 'Anomaly', 'System', 'Anomaly.System'),
(1005, 'Anomaly', 'Application', 'Anomaly.Application'),
(1006, 'Anomaly', 'Behaviour', 'Anomaly.Behaviour'),
(9998, 'Other', '', 'Other'),
(9999, 'Test', '', 'Test');
-- --------------------------------------------------------
--
-- Table structure for table `clients`
--
CREATE TABLE IF NOT EXISTS `clients` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registered` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`requestor` varchar(256) NOT NULL,
`hostname` varchar(256) NOT NULL,
`service` varchar(256) NOT NULL,
`note` text NOT NULL,
`valid` tinyint(1) NOT NULL DEFAULT '1',
`identity` varchar(64) NOT NULL,
`secret` varchar(16) NULL,
`read` tinyint(1) NOT NULL DEFAULT '1',
`debug` tinyint(1) NOT NULL DEFAULT '0',
`write` tinyint(1) NOT NULL DEFAULT '0',
`test` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci AUTO_INCREMENT=31 ;
--
-- Dumping data for table `clients`
--
INSERT INTO `clients` (`id`, `registered`, `requestor`, `hostname`, `service`, `note`, `valid`, `identity`, `secret`, `read`, `debug`, `write`, `test`) VALUES
(1, '0000-00-00 00:00:00', '', 'afrodita.civ.zcu.cz', 'hihat', '', 1, 'cz.zcu.civ.afrodita.hihat', NULL, 1, 0, 1, 0),
(2, '0000-00-00 00:00:00', '', 'afrodita.civ.zcu.cz', 'labrea', '', 1, 'cz.zcu.civ.afrodita.labrea', NULL, 1, 0, 1, 0),
(3, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'cesnet_ids', '', 1, 'cz.cesnet.au1.cesnet_ids', NULL, 1, 0, 1, 0),
(4, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'cesnet_sserv', '', 1, 'cz.cesnet.au1.cesnet_sserv', NULL, 1, 0, 1, 0),
(5, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'n6d-dorkbot', '', 1, 'cz.cesnet.au1.n6d-dorkbot', NULL, 1, 0, 1, 0),
(6, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'n6e-certplsinkhole', '', 1, 'cz.cesnet.au1.n6e-certplsinkhole', NULL, 1, 0, 1, 0),
(7, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'n6i-citadelsinkhole', '', 1, 'cz.cesnet.au1.n6i-citadelsinkhole', NULL, 1, 0, 1, 0),
(8, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'n6i-citadelsinkholeqd', '', 1, 'cz.cesnet.au1.n6i-citadelsinkholeqd', NULL, 1, 0, 1, 0),
(9, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'n6n-openntp', '', 1, 'cz.cesnet.au1.n6n-openntp', NULL, 1, 0, 1, 0),
(10, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'n6o-botszeroaccess', '', 1, 'cz.cesnet.au1.n6o-botszeroaccess', NULL, 1, 0, 1, 0),
(11, '0000-00-00 00:00:00', '', 'au1.cesnet.cz', 'report_n6v-virut', '', 1, 'cz.cesnet.au1.report_n6v-virut', NULL, 1, 0, 1, 0),
(12, '0000-00-00 00:00:00', '', 'au2.cesnet.cz', 'ids-cz', '', 1, 'cz.cesnet.au2.ids-cz', NULL, 1, 0, 1, 0),
(13, '0000-00-00 00:00:00', '', 'bee.net.vutbr.cz', 'hpscan', '', 1, 'cz.vutbr.net.bee.hpscan', NULL, 1, 0, 1, 0),
(14, '0000-00-00 00:00:00', '', 'buldog.vsb.cz', 'kippo', '', 1, 'cz.vsb.buldog.kippo', NULL, 1, 0, 1, 0),
(15, '0000-00-00 00:00:00', '', 'collector-nemea.liberouter.org', 'nemea', '', 1, 'org.liberouter.collector-nemea.nemea', NULL, 1, 0, 1, 0),
(16, '0000-00-00 00:00:00', '', 'collector.liberouter.org', 'hoststats', '', 1, 'org.liberouter.collector.hoststats', NULL, 1, 0, 1, 0),
(17, '0000-00-00 00:00:00', '', 'collector.liberouter.org', 'synscandetector_1_0', '', 1, 'org.liberouter.collector.synscandetector_1_0', NULL, 1, 0, 1, 0),
(18, '0000-00-00 00:00:00', '', 'holly.cesnet.cz', 'kippohoneypot', '', 1, 'cz.cesnet.holly.kippohoneypot', NULL, 1, 0, 1, 0),
(19, '0000-00-00 00:00:00', '', 'kryten.cesnet.cz', 'dionaeahoneypot', '', 1, 'cz.cesnet.kryten.dionaeahoneypot', NULL, 1, 0, 1, 0),
(20, '0000-00-00 00:00:00', '', 'mentat.cesnet.cz', 'mentat', '', 1, 'cz.cesnet.mentat.mentat', NULL, 1, 0, 1, 0),
(21, '0000-00-00 00:00:00', '', 'miel.opf.slu.cz', 'kippo', '', 1, 'cz.slu.opf.miel.kippo', NULL, 1, 0, 1, 0),
(22, '0000-00-00 00:00:00', '', 'nfsen.ics.muni.cz', 'honeyscan', '', 1, 'cz.muni.ics.nfsen.honeyscan', NULL, 1, 0, 1, 0),
(23, '0000-00-00 00:00:00', '', 'nfsen.ics.muni.cz', 'scandetector_1_0', '', 1, 'cz.muni.ics.nfsen.scandetector_1_0', NULL, 1, 0, 1, 0),
(24, '0000-00-00 00:00:00', '', 'nfsen.ics.muni.cz', 'sshbruteforce-1_n', '', 1, 'cz.muni.ics.nfsen.sshbruteforce-1_n', NULL, 1, 0, 1, 0),
(25, '0000-00-00 00:00:00', '', 'vinovago.cesnet.cz', 'fail2ban', '', 1, 'cz.cesnet.vinovago.fail2ban', NULL, 1, 0, 1, 0),
(26, '0000-00-00 00:00:00', '', 'ward.tul.cz', 'dionaeatul', '', 1, 'cz.tul.ward.dionaeatul', NULL, 1, 0, 1, 0),
(27, '0000-00-00 00:00:00', '', 'ward.tul.cz', 'kippo', '', 1, 'cz.tul.ward.kippo', NULL, 1, 0, 1, 0),
(28, '0000-00-00 00:00:00', 'kostenec@civ.zcu.cz', 'kostik.zcu.cz', 'com.example.test-node', '', 1, 'com.example.test-node', "Phaipe5ush7p", 1, 0, 0, 0),
(29, '0000-00-00 00:00:00', 'kostenec@civ.zcu.cz', 'kostik.zcu.cz', 'com.example.test-node2', '', 1, 'com.example.test-node2', NULL, 1, 0, 0, 0),
(30, '0000-00-00 00:00:00', 'kostenec@civ.zcu.cz', 'kostik.zcu.cz', 'Test', '', 1, 'com.example.test-node3', NULL, 1, 0, 0, 0),
(31, '2014-12-11 13:51:18', 'ph@cesnet.cz', 'grey.cesnet.cz', 'Test', '', 1, 'cz.cesnet.grey.test', "co3kaero5Ruv", 1, 1, 1, 0);
-- --------------------------------------------------------
--
-- Table structure for table `events`
--
CREATE TABLE IF NOT EXISTS `events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`received` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`client_id` int(11) NOT NULL,
`data` text NOT NULL,
`valid` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `id` (`id`,`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
--
-- Table structure for table `event_category_mapping`
--
CREATE TABLE IF NOT EXISTS `event_category_mapping` (
`event_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
KEY `event_id_2` (`event_id`,`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `event_tag_mapping`
--
CREATE TABLE IF NOT EXISTS `event_tag_mapping` (
`event_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
KEY `event_id_2` (`event_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `last_events`
--
CREATE TABLE IF NOT EXISTS `last_events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`client_id` int(11) NOT NULL,
`event_id` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `client_id` (`client_id`,`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
--
-- Table structure for table `tags`
--
CREATE TABLE IF NOT EXISTS `tags` (
`id` int(11) NOT NULL,
`tag` varchar(64) NOT NULL,
KEY `id_tag_name` (`id`,`tag`),
KEY `tag_name` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
--
-- Dumping data for table `tags`
--
INSERT INTO `tags` (`id`, `tag`) VALUES
(1, 'Connection'),
(2, 'Datagram'),
(3, 'Content'),
(4, 'Data'),
(5, 'File'),
(6, 'Flow'),
(7, 'Log'),
(8, 'Protocol'),
(9, 'Host'),
(10, 'Network'),
(11, 'Correlation'),
(12, 'External'),
(13, 'Reporting'),
(99, 'Other');
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
This diff is collapsed.
BSD License
Copyright © 2011-2015 Cesnet z.s.p.o
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Cesnet z.s.p.o nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE Cesnet z.s.p.o BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------+
| Warden Client Library 3.0-beta3 |
+---------------------------------+
Content
A. Introduction
B. Quick start (TL;DR)
C. Concepts
D. HTTP/JSON API
E. Python API
------------------------------------------------------------------------------
A. Introduction
The main goal of Warden 3 is to address the shortcomings, which emerged
during several years of Warden 2.X operation. Warden 3 uses flexible and
descriptive event format, based on JSON. Warden 3 protocol is based on plain
HTTPS queries with help of JSON (Warden 2 SOAP is heavyweight, outdated and
draws in many dependencies). Clients can be multilanguage, unlike SOAP/HTTPS,
plain HTTPS and JSON is mature in many mainstream programming languages.
Server is written in Python - mature language with consistent and coherent
libraries and many skilled developers.
------------------------------------------------------------------------------
B. Quick start (TL;DR)
* Obtain X509 key/cert, corresponding with DNS name of you machine.
* Obtain X509 CA chain for server validation.
* Choose client name ("reverse DNS", like org.example.warden.client, but
it does not necessary need to correspond to your machine's DNS name).
* Ask Warden server admins for registration. They will want to know at least
client name and dns name, and short description of the (planned) client
and its purpose. Work with them. They may request some changes or
clarifications, offer you useful guidelines, provide you with alternative
sandbox URL, etc.
If succesful, you will receive authentication secret.
* Use warden_curl_test.sh to check you are able to talk to server.
* See warden_client_examples.py on how to integrate sending/receiving
into your Python application.
* Alternatively, check 'contrib' directory in Warden GIT for various
ready to use tools or recipes. You may find senders for various
honeypots, or warden_filer may get handy if you do not want to delve
into Python at all.
* Welcome! Thanks for participating in in the data exchange to improve
network security awareness.
------------------------------------------------------------------------------
C. Concepts
C.1. Event description format
IDEA - Intrusion Detection Extensible Alert, flexible extensible format
for security events, see:
https://idea.cesnet.cz/
C.2. Event serial ID
Each received event gets assigned integer serial number. These numbers are
sequential, so each recipient can keep track of the last event "id" it
received and next time ask only for following events.
C.3. Authentication
In Warden 2, clients get authenticated by server certificate, however
server certificate is usually same for the whole machine, so individual
clients are differentiated only by telling their own name. However, client name
is widely known, so this allows for client impersonation within one machine.
Warden 3 slightly improves this schema by replacing client name in
authentication phase by "secret", random string, shared among particular
client and main server, which makes it harder to forge client identity (be it
by mistake or intentional).
However, best solution for these cases is of course specific certificate
for each particular client (which is also fully supported).
Client also has to have server CA certificate (or chain) at its disposal
to be able to verify server authenticity.
C.4. Client name
Unlike Warden 2, client names in Warden 3 have hierarchy. Modelled after
Java class names, client name is dot separated list of labels, with
significance from left to right – leftmost denoting largest containing realm,
rightmost denoting single entity.
Country.organisation.suborganizations.machine.local realm scheme akin to
"org.example.csirt.northwest.honeypot.jabberwock" is strongly recommended.
Label case is significant, label can contain only letters, numbers or
underscore and must not start with number.
The reason is the possibility to filter incoming events based not only on
particular client, or (for some recipients flawed) notion of "own" messages,
but based on wider units.
------------------------------------------------------------------------------
D. HTTP/JSON API
Client must know the base URL of the Warden server. Warden 3 accepts
queries on paths under base URL (which correspond to called method), with
usual query string variable=data pairs separated by ampersand as arguments.
Multivalues are specified by repeating same variable with each value several
times.
https://warden.example.org/warden3/getEvents?secret=PwD&cat=Abusive.Spam&cat=Fraud.Phishing
\________________ _______________/ \___ ___/ \____ ___/ \______ _______/ \________ _______/
V V V V V
Base URL --' | | | |
Called method ------------------------' | | |
Key/value pair -----------------------------------' | |
Multivalue ------------------------------------------------'------------------'
Method may expect bulk data (events to save, for example) - query then
must be POST, with POST JSON data, formed appropriately as documented in
particular method.
If HTTPS call succeeds (200 OK), method returns JSON object containing
requested data.
D.1. Error handling
Should the call fail, server returns HTTP status code, together with JSON
object, describing the errors (there may be multiple ones, especially when
sending events). The keys of the object, which may be available, are:
* method - name of the method called
* req_id - unique identifier or the request (for troubleshooting, Warden
administrator can uniquely identify related log lines)
* errors - always present list of JSON objects, which contain:
* error - HTTP status code
* message - human readable error description
* Other context dependent fields may appear, see particular method
description.
Client errors (4xx) are considered permanent - client must not try to send
same event again as it will always get rejected - client administrator
will need to inspect logs and rectify the cause.
Server errors (5xx) may be considered by client as temporary and client is
advised to try again after reasonable recess.
D.2. Common arguments
* secret - shared secret, assigned to client during registration
* client - client name, optional, can be used to mimic Warden 2
authentication behavior if explicitly allowed for this client by server
administrator
= getEvents =
Fetches events from server.
Arguments:
* count - number of requested events
* id - starting serial number requested, id of all received events will
be greater
* cat, nocat - selects only events with categories, which are/are not
present in the event Category field (mutually exclusive)
* group, nogroup - selects only events originated/not originated from
this realms and/or client names, as denoted in the event Node.Name field
(mutually exclusive)
* tag, notag - selects only events with/without this client description
tags, as denoted in the event Node.Type field (mutually exclusive)
Returns:
* lastid - serial number of the last received event
* events - array of Idea events
Example:
$ curl \
--key key.pem \
--cert cert.pem \
--cacert ca.pem \
--connect-timeout 3 \
--request POST \
\
"https://warden.example.org/getEvents?\
secret=SeCrEt\
&count=1\
&nogroup=org.example\
&cat=Abusive.Spam\
&cat=Fraud.Phishing"
{"lastid": 581,
"events": [{
"Format": "IDEA0",
"DetectTime": "2015-02-03T09:55:21.563638Z",
"Target": [{"URL": ["http://example.com/kocHq"]}],
"Category": ["Fraud.Phishing"],
"Note": "Example event"}]}
= sendEvents =
Uploads events to server.
Arguments:
* POST data - JSON array of Idea events
Returns:
Returns object with number of saved messages in "saved" attribute.
In case of error, multiple errors may be returned in "errors" list (see
[[Warden3#Error-handling|Error handling]] section). Each of the error objects
may contain "events" key with list of indexes of events affected by this
particular error. If there is error object without "events" key, caller
must consider all events affected.
Should the call fail because of errors in just couple of events, error
message will contain JSON object in "detail.errors" section. The keys of the
object are indexes into POST data array, values are error messages for each
particular failed Idea event.
Example:
$ eventid=$RANDOM$RANDOM$RANDOM$RANDOM$RANDOM
$ detecttime=$(date --rfc-3339=seconds|tr " " "T")
$ client="cz.example.warden.test"
$ printf '
[
{
"Format": "IDEA0",
"ID": "%s",
"DetectTime": "%s",
"Category": ["Test"],
"Node": [{"Name": "%s"}]
}
]' $eventid $detecttime $client |\
curl \
--key $keyfile \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
--data-binary "@-" \
"https://warden.example.org/sendEvents?client=$client&secret=SeCrEt"
{"saved":1}
(However note that this is not the best way to generate Idea messages. :) )
Example with error:
$ curl \
--key $keyfile \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
--data-binary '[{"Format": "IDEA0","ID":"ASDF","Category":[],"DetectTime":"asdf"}]' \
"https://warden.example.org/sendEvents?client=cz.example.warden.test&secret=SeCrEt"
{"errors":
[
{"message": "Validation error: key \"DetectTime\", value \"asdf\", expected - RFC3339 timestamp.",
"events": [0],
"error": 460
}
],
"method": "sendEvents",
"req_id": 3726454025
}
= getInfo =
Returns basic server information.
Returns:
* version - Warden server version string
* description - server greeting
* send_events_limit - sendEvents will be rejected if client sends more
events in one call
* get_events_limit - getEvents will return at most that much events
Example:
$ curl \
--key key.pem \
--cert cert.pem \
--cacert ca.pem \
--connect-timeout 3 \
--request POST \
"https://warden.example.org/getInfo?secret=SeCrEt"
{"version": "3.0",
"send_events_limit": 500,
"get_events_limit": 1000,
"description": "Warden 3 server"}
E. Python API
Python API tries to abstract from raw HTTPS/URL/JSON details. User
instantiates Client class with necessary settings (certificates, secret,
client name, logging, limits, ...) and then uses its method to access server.
= Client constructor =
wclient = warden.Client(
url,
certfile=None,
keyfile=None,
cafile=None,
timeout=60,
retry=3,
pause=5,
get_events_limit=6000,
send_events_limit=500,
errlog={},
syslog=None,
filelog=None,
idstore=None,
name="org.example.warden_client",
secret=None)
* url - Warden server base URL
* certfile, keyfile, cafile - paths to X509 material
* timeout - network timeout value in seconds
* retry - number retries on transitional errors during sending events
* pause - wait time in seconds between transitional error retries
* get_events_limit - maximum number of events to receive (note that server
may have its own notion)
* send_events_limit - when sending, event lists will be split and sent by
chunks of at most this size (note that used value will get adjusted according
to the limit reported by server)
* errlog - stderr logging configuration dict
* level - most verbose loglevel to log
* syslog - syslog logging configuration dict
* level - most verbose loglevel to log
* socket - syslog socket path (defaults to "/dev/log")
* facility - syslog facility (defaults to "local7")
* filelog - file logging configuration dict
* level - most verbose loglevel to log
* file - path to log file
* idstore - path to simple text file, in which last received event ID gets
stored. If None, server notion is used
* name - client name
* secret - authentication secret
= Configuration file helper =
warden.read_cfg(cfgfile)
Warden object can get initialized from JSON like configuration file. It's
essentially JSON, but full line comments, starting with "#" or "//", are
allowed. read_cfg reads the configuration file and returns dict suitable
for passing as Client constructor arguments.
Usage example:
wclient = warden.Client(**warden.read_cfg("warden_client.cfg"))
= warden.Client.getEvents =
wclient.getEvents(
id=None,
idstore=None,
count=1,
cat=None, nocat=None,
tag=None, notag=None,
group=None, nogroup=None)
* id - can be used to explicitly override value from idstore file
* idstore - can be used to explicitly override idstore for this request
* count - number of requested events
* cat, nocat - selects only events with categories, which are/are not
present in the event Category field (mutually exclusive)
* group, nogroup - selects only events originated/not originated from
this realms and/or client names, as denoted in the event Node.Name field
(mutually exclusive)
* tag, notag - selects only events with/without this client description
tags, as denoted in the event Node.Type field (mutually exclusive)
Returns:
* list of Idea events
= warden.Client.sendEvents =
wclient.sendEvents(self, events=[], retry=None, pause=None):
* events - list of Idea events to be sent to server
* retry - use this retry value just for this call instead from value from
constructor
* pause - use this pause value just for this call instead from value from
constructor
Returns:
* dict with number of sent events under "saved" key
Note:
events list length is limited only by available resources, sendEvents
will split it and send separately in at most send_events_limit long chunks
(however note that sendEvents will also need additional memory for its
internal data structures).
Server errors (5xx) are considered transitional and sendEvents will do
retry number of attempts to deliver corresponding events, delayed by
pause seconds.
Should the call fail because of errors, particular errors may contain
"events" list. Values of the list are then indexes into POST data array. If
no "events" list is present, all events attempted to send must be
considered as failed (with this particular error). See also
[[Warden3#Error-handling|Error handling]] section.
Errors may also contain event IDs from Idea messages in "events_id" list.
This is primarily for logging - client administrator may identify offending
messages by stable identifiers.
= warden.Client.getInfo =
wclient.getInfo()
Returns dictionary of information from getInfo Warden call.
= Error class =
Error(
message,
logger=None,
error=None,
prio="error",
method=None,
req_id=None,
detail=None,
exc=None)
Class, which gets returned in case of client or server error. Caller can
test whether it received data or error by checking:
isinstance(res, Error).
However if he does not want to deal with errors altogether, this error
object also returns False value if used in Bool context and acts as an
empty iterator - in following examples do_stuff() is not evaluated:
if res:
do_stuff(res)
for e in res:
do_stuff(e)
str(Error_Instance) outputs formatted error, info_str() and
debug_str() output increasingly more detailed info.
------------------------------------------------------------------------------
Copyright (C) 2011-2022 Cesnet z.s.p.o
{
"url": "https://warden-hub.example.org/warden3",
"certfile": "cert.pem",
"keyfile": "key.pem",
"filelog": {"level": "debug"},
"name": "org.example.warden_client",
"secret": "ToP_SeCrEt"
}
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2011-2013 Cesnet z.s.p.o
# Copyright (C) 2011-2015 Cesnet z.s.p.o
# Use of this source is governed by a 3-clause BSD-style license, see LICENSE file.
from warden_client import Client, Error, read_cfg
import json
import string
from time import time, gmtime
from math import trunc
from time import time
from uuid import uuid4
from pprint import pprint
from os import path
from random import randint, randrange, choice, random;
from base64 import b64encode;
def get_precise_timestamp():
t = time()
us = trunc((t-trunc(t))*1000000)
g = gmtime(t)
iso = '%04d-%02d-%02dT%02d:%02d:%02d.%0dZ' % (g[0:6]+(us,))
return iso
from random import randint, randrange, choice, random
from base64 import b64encode
from warden_client import Client, Error, read_cfg, format_timestamp
def gen_min_idea():
return {
"Format": "IDEA0",
"ID": str(uuid4()),
"DetectTime": get_precise_timestamp(),
"DetectTime": format_timestamp(),
"Category": ["Test"],
}
......@@ -63,18 +53,18 @@ def gen_random_idea(client_name="cz.example.warden.test"):
def randip6():
return [rand6ip, geniprange(rand6ip), rand6cidr][randint(0, 2)]()
def randstr(charlist=string.letters, maxlen=32, minlen=1):
def randstr(charlist=string.ascii_letters, maxlen=32, minlen=1):
return ''.join(choice(charlist) for i in range(randint(minlen, maxlen)))
event = {
"Format": "IDEA0",
"ID": str(uuid4()),
"CreateTime": get_precise_timestamp(),
"DetectTime": get_precise_timestamp(),
"WinStartTime": get_precise_timestamp(),
"WinEndTime": get_precise_timestamp(),
"EventTime": get_precise_timestamp(),
"CeaseTime": get_precise_timestamp(),
"CreateTime": format_timestamp(),
"DetectTime": format_timestamp(),
"WinStartTime": format_timestamp(),
"WinEndTime": format_timestamp(),
"EventTime": format_timestamp(),
"CeaseTime": format_timestamp(),
#"Category": ["Abusive.Spam","Abusive.Harassment","Malware","Fraud.Copyright","Test","Fraud.Phishing","Fraud.Scam"],
# "Category": ["Abusive.Spam","Fraud.Copyright"],
"Category": [choice(["Abusive.Spam","Abusive.Harassment","Malware","Fraud.Copyright","Test","Fraud.Phishing","Fraud.Scam"]) for dummy in range(randint(1, 3))],
......@@ -113,22 +103,25 @@ def gen_random_idea(client_name="cz.example.warden.test"):
"Size": 46,
"Ref": ["cve:CVE-%s-%s" % (randstr(string.digits, 4), randstr())],
"ContentEncoding": "base64",
"Content": b64encode(randstr())
"Content": b64encode(randstr().encode('ascii')).decode("ascii")
}
],
"Node": [
{
"Name": client_name,
"Tags": [choice(["Data", "Protocol", "Honeypot", "Heuristic", "Log"]) for dummy in range(randint(1, 3))],
"Type": [choice(["Data", "Protocol", "Honeypot", "Heuristic", "Log"]) for dummy in range(randint(1, 3))],
"SW": ["Kippo"],
"AggrWin": "00:05:00"
},
{
"Name": "org.example.warden.client",
"Type": [choice(["Connection", "Datagram"]) for dummy in range(randint(1, 2))],
}
]
}
return event
def main():
wclient = Client(**read_cfg("warden_client.cfg"))
# Also inline arguments are possible:
......@@ -143,44 +136,53 @@ def main():
# idstore="MyClient.id",
# name="cz.example.warden.test")
print "=== Debug ==="
print("=== Debug ===")
info = wclient.getDebug()
if not isinstance(info, Error):
pprint(info)
print "=== Server info ==="
pprint(info)
# All methods return something.
# If you want to catch possible errors (for example implement some
# form of persistent retry, or save failed events for later, you may
# check for Error instance and act based on contained info.
# If you want just to be informed, this is not necessary, just
# configure logging correctly and check logs.
if isinstance(info, Error):
print(info)
print("=== Server info ===")
info = wclient.getInfo()
if not isinstance(info, Error):
pprint(info)
print "=== Sending 10 event(s) ==="
print("=== Sending 10 event(s) ===")
start = time()
ret = wclient.sendEvents([gen_random_idea(client_name=wclient.name) for i in range(10)])
print ret
print "Time: %f" % (time()-start)
print(ret)
print("Time: %f" % (time()-start))
print "=== Getting 10 events ==="
print("=== Getting 10 events ===")
start = time()
# cat = ['Availability', 'Abusive.Spam','Attempt.Login']
# cat = ['Attempt', 'Information','Fraud.Scam','Malware.Virus']
cat = ['Fraud', 'Abusive.Spam']
nocat = ['Availability', 'Information', 'Fraud.Scam']
tag = ['Log', 'Data']
notag = ['Flow', 'Datagram']
group = ['cz.tul.ward.kippo','cz.vsb.buldog.kippo']
nogroup = ['cz.zcu.civ.afrodita','cz.vutbr.net.bee.hpscan']
ret = wclient.getEvents(count=10, cat=cat, nocat=None, tag=tag, notag=None, group=None, nogroup=nogroup)
print "Time: %f" % (time()-start)
print "Got %i events" % len(ret)
# cat = ['Fraud', 'Abusive.Spam']
# nocat = ['Availability', 'Information', 'Fraud.Scam']
cat = []
nocat = []
#tag = ['Log', 'Data']
#notag = ['Flow', 'Datagram']
tag = []
notag = []
#group = ['cz.tul.ward.kippo','cz.vsb.buldog.kippo']
#nogroup = ['cz.zcu.civ.afrodita','cz.vutbr.net.bee.hpscan']
group = []
nogroup = []
ret = wclient.getEvents(count=10, cat=cat, nocat=nocat, tag=tag, notag=notag, group=group, nogroup=nogroup)
print("Time: %f" % (time()-start))
print("Got %i events" % len(ret))
for e in ret:
print e["Category"], e["Node"][0]["Tags"], e["Node"][0]["Name"]
if isinstance(ret, Error):
print ret
print(e.get("Category"), e.get("Node")[0].get("Type"), e.get("Node")[0].get("Name"))
if __name__ == "__main__":
main()
#!/bin/sh
#
# Copyright (C) 2011-2013 Cesnet z.s.p.o
# Copyright (C) 2011-2015 Cesnet z.s.p.o
# Use of this source is governed by a 3-clause BSD-style license, see LICENSE file.
keyfile='key.pem'
certfile='cert.pem'
cafile='tcs-ca-bundle.pem'
if [ "$#" -ne 6 ]; then
echo "Run me like:"
echo "${0##*/} 'https://warden-hub.example.org/warden3' org.example.warden.client 'ToPsEcReT' key.pem cert.pem tcs-ca-bundle.pem"
exit 1
fi
url="$1"
client="$2"
secret="$3"
# --fail \
# --show-error \
#
keyfile="$4"
certfile="$5"
cafile="$6"
echo "Test 404"
curl \
......@@ -20,7 +23,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/blefub?client=$client&secret=$secret"
echo
......@@ -30,7 +32,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/?client=$client&secret=$secret"
echo
......@@ -40,7 +41,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client"
echo
......@@ -50,7 +50,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents"
echo
......@@ -60,7 +59,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=asdf.blefub"
echo
......@@ -70,7 +68,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=asdf.blefub&secret=$secret"
echo
......@@ -80,7 +77,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=ASDFblefub"
echo
......@@ -90,7 +86,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?secret=$secret"
echo
......@@ -111,7 +106,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=$secret&cat=bflm"
echo
......@@ -121,7 +115,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=$secret&cat=Other&nocat=Test"
echo
......@@ -142,7 +135,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=$secret&self=test"
echo
......@@ -152,7 +144,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=$secret&bad=guy"
echo
......@@ -162,7 +153,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=$secret"
echo
......@@ -172,7 +162,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getEvents?client=$client&secret=$secret&count=3&id=10"
echo
......@@ -182,7 +171,6 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getDebug?client=$client&secret=$secret"
echo
......@@ -192,12 +180,5 @@ curl \
--cert $certfile \
--cacert $cafile \
--connect-timeout 3 \
--request POST \
"$url/getInfo?client=$client&secret=$secret"
echo
#curl \
# --fail \
# --connect-timeout 3 \
# --request POST \
# $url/getEvents
BSD License
Copyright © 2011-2015 Cesnet z.s.p.o
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Cesnet z.s.p.o nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE Cesnet z.s.p.o BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This diff is collapsed.
#!/bin/bash
script=${0##*/}
warn=0
crit=65536
read -rd '' helps <<EOF
$script: Icinga plugin to check too high number of files in directory.
Usage: $script -d dir [-w num] [-c num] [-h ]
-d dir directory to watch
-w num warning if number of files exceeds this value (default $warn)
-c num critical if number of files exceeds this value (default $crit)
EOF
function bailout {
echo -n "$script" | tr '[:lower:]' '[:upper:]'
echo " $2 $3"
exit "$1"
}
while getopts hvVd:w:c: opt; do
case "$opt" in
h) bailout 3 "UNKNOWN" "$helps";;
d) dir="$OPTARG";;
w) warn="$OPTARG";;
c) crit="$OPTARG";;
"?") bailout 3 "UNKNOWN" "Unknown option, use -h for help";;
esac
done
[ -z "$dir" ] && bailout 3 "UNKNOWN" "-d not specified"
count=$(find "$dir" -mindepth 1 -maxdepth 1 | wc -l)
[ "$count" -gt "$crit" ] && bailout 2 "CRIT" "$count"
[ "$count" -gt "$warn" ] && bailout 1 "WARN" "$count"
bailout 0 "OK" "$count"
This diff is collapsed.
This diff is collapsed.
# You may want to review and/or change the logfile path, user/group in
# 'create' and daemon to restart in 'postrotate'
/var/log/warden_filer.log
{
rotate 52
weekly
missingok
notifempty
compress
delaycompress
dateext
create 640 mentat mentat
postrotate
/etc/init.d/warden_filer_sender restart
/etc/init.d/warden_filer_receiver restart
endscript
}
This diff is collapsed.