security/crowdsec 1.0.2: updated cron and log parsing (#3269)

This commit is contained in:
mmetc 2023-03-01 15:19:14 +01:00 committed by GitHub
parent b47dabccc2
commit c7240f4836
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 158 additions and 146 deletions

View file

@ -1,5 +1,5 @@
PLUGIN_NAME= crowdsec
PLUGIN_VERSION= 1.0.1
PLUGIN_VERSION= 1.0.2
PLUGIN_DEPENDS= crowdsec
PLUGIN_COMMENT= Lightweight and collaborative security engine
PLUGIN_MAINTAINER= marco@crowdsec.net

View file

@ -8,6 +8,12 @@ WWW: https://crowdsec.net/
Plugin Changelog
================
1.0.2
* updated cron job (reload only when there are updates), added small random delay
* limit log collection to latest.log (requires 22.7+)
* some javascript lint
1.0.1
* fixed live logs

View file

@ -6,4 +6,4 @@
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
#minute hour mday month wday who command
0 1,13 * * * root /usr/local/opnsense/scripts/OPNsense/CrowdSec/hub-upgrade.sh
0 1 * * * root (sleep $(jot -r 1 1 60); /usr/local/opnsense/scripts/OPNsense/CrowdSec/hub-upgrade.sh)

View file

@ -7,9 +7,12 @@
#
filenames:
# ssh
- /var/log/audit/*.log
# web admin
- /var/log/lighttpd/*.log
# DO NOT EDIT - to add new datasources (log locations),
# create new files in /usr/local/etc/crowdsec/acquis.d/
#
# collection: crowdsecurity/sshd
- /var/log/audit/latest.log
# collection: crowdsecurity/opnsense-gui (web admin)
- /var/log/lighttpd/latest.log
labels:
type: syslog

View file

@ -1,7 +1,7 @@
<model>
<mount>//OPNsense/crowdsec/general</mount>
<description>CrowdSec general configuration</description>
<version>1.0.1</version>
<version>1.0.2</version>
<items>
<agent_enabled type="BooleanField">

View file

@ -1,7 +1,6 @@
{# SPDX-License-Identifier: MIT #}
{# SPDX-FileCopyrightText: © 2021 CrowdSec <info@crowdsec.net> #}
<script>
$( document ).ready(function() {
var data_get_map = {'frm_GeneralSettings':"/api/crowdsec/general/get"};
@ -22,7 +21,7 @@
});
});
if(window.location.hash != "") {
if(window.location.hash !== "") {
$('a[href="' + window.location.hash + '"]').click()
}
$('.nav-tabs a').on('shown.bs.tab', function (e) {

View file

@ -1,16 +1,21 @@
#!/bin/sh
/usr/local/bin/cscli --error hub update \
&& /usr/local/bin/cscli --error hub upgrade
test -x /usr/local/bin/cscli || exit 0
/usr/local/bin/cscli --error hub update
upgraded=$(/usr/local/bin/cscli --error hub upgrade)
if [ ! -e "/usr/local/etc/crowdsec/collections/opnsense.yaml" ]; then
/usr/local/bin/cscli --error collections install crowdsecurity/opnsense
fi
if service crowdsec enabled; then
if ! service crowdsec status >/dev/null 2>&1; then
service crowdsec start >/dev/null 2>&1 || :
else
service crowdsec reload >/dev/null 2>&1 || :
if [ -n "$upgraded" ]; then
if service crowdsec enabled; then
if ! service crowdsec status >/dev/null 2>&1; then
service crowdsec start >/dev/null 2>&1 || :
else
service crowdsec reload >/dev/null 2>&1 || :
fi
fi
fi

View file

@ -1,27 +1,27 @@
/*global moment, $ */
/*exported CrowdSec */
/*eslint no-undef: "error"*/
/*eslint semi: "error"*/
/* global moment, $ */
/* exported CrowdSec */
/* eslint no-undef: "error" */
/* eslint semi: "error" */
var CrowdSec = (function() {
var CrowdSec = (function () {
'use strict';
var _refresh_template = '<button class="btn btn-default" type="button" title="Refresh"><span class="icon glyphicon glyphicon-refresh"></span></button>';
var _refreshTemplate = '<button class="btn btn-default" type="button" title="Refresh"><span class="icon glyphicon glyphicon-refresh"></span></button>';
var _dataFormatters = {
yesno: function(column, row) {
yesno: function (column, row) {
return _yesno2html(row[column.id]);
},
delete: function(column, row) {
delete: function (column, row) {
var val = row.id;
if (isNaN(val)) {
return '';
}
return '<button type="button" class="btn btn-secondary btn-sm" value="'+val+'" onclick="CrowdSec.deleteDecision('+val+')"><i class="fa fa-trash" /></button>';
return '<button type="button" class="btn btn-secondary btn-sm" value="' + val + '" onclick="CrowdSec.deleteDecision(' + val + ')"><i class="fa fa-trash" /></button>';
},
duration: function(column, row) {
duration: function (column, row) {
var duration = row[column.id];
if (!duration) {
return 'n/a';
@ -29,89 +29,89 @@ var CrowdSec = (function() {
return $('<div>').attr({
'data-toggle': 'tooltip',
'data-placement': 'left',
'title': duration
title: duration
}).text(_humanizeDuration(duration)).prop('outerHTML');
},
datetime: function(column, row) {
datetime: function (column, row) {
var dt = row[column.id];
var parsed = moment(dt);
if (!dt) {
return '';
}
if (!parsed.isValid()) {
console.error("Cannot parse timestamp: %s", dt);
console.error('Cannot parse timestamp: %s', dt);
return '???';
}
return $('<div>').attr({
'data-toggle': 'tooltip',
'data-placement': 'left',
'title': parsed.format()
title: parsed.format()
}).text(_humanizeDate(dt)).prop('outerHTML');
},
}
};
function _parseDuration(duration) {
function _parseDuration (duration) {
var re = /(-?)(?:(?:(\d+)h)?(\d+)m)?(\d+).\d+(m?)s/m;
var matches = duration.match(re);
var seconds = 0;
if (!matches.length) {
throw new Error("Unable to parse the following duration: " + duration + ".");
throw new Error('Unable to parse the following duration: ' + duration + '.');
}
if (typeof matches[2] !== "undefined") {
if (typeof matches[2] !== 'undefined') {
seconds += parseInt(matches[2], 10) * 3600; // hours
}
if (typeof matches[3] !== "undefined") {
if (typeof matches[3] !== 'undefined') {
seconds += parseInt(matches[3], 10) * 60; // minutes
}
if (typeof matches[4] !== "undefined") {
if (typeof matches[4] !== 'undefined') {
seconds += parseInt(matches[4], 10); // seconds
}
if ("m" === parseInt(matches[5], 10)) {
if (parseInt(matches[5], 10) === 'm') {
// units in milliseconds
seconds *= 0.001;
}
if ("-" === parseInt(matches[1], 10)) {
if (parseInt(matches[1], 10) === '-') {
// negative
seconds = -seconds;
}
return seconds;
}
function _updateFreshness(selector, timestamp) {
function _updateFreshness (selector, timestamp) {
var $freshness = $(selector).find('.actionBar .freshness');
if (timestamp) {
$freshness.data('refresh_timestamp', timestamp);
} else {
timestamp = $freshness.data('refresh_timestamp');
}
var howlong_human = '???';
var howlongHuman = '???';
if (timestamp) {
var howlong_ms = moment() - moment(timestamp);
howlong_human = moment.duration(howlong_ms).humanize();
var howlongms = moment() - moment(timestamp);
howlongHuman = moment.duration(howlongms).humanize();
}
$freshness.text(howlong_human + ' ago');
$freshness.text(howlongHuman + ' ago');
}
function _addFreshness(selector) {
function _addFreshness (selector) {
// this creates one timer per tab
var freshness_template = '<span style="float:left">Last refresh: <span class="freshness"></span></span>';
$(selector).find('.actionBar').prepend(freshness_template);
setInterval(function() {
var freshnessTemplate = '<span style="float:left">Last refresh: <span class="freshness"></span></span>';
$(selector).find('.actionBar').prepend(freshnessTemplate);
setInterval(function () {
_updateFreshness(selector);
}, 5000);
}
function _humanizeDate(text) {
function _humanizeDate (text) {
return moment(text).fromNow();
}
function _humanizeDuration(text) {
function _humanizeDuration (text) {
return moment.duration(_parseDuration(text), 'seconds').humanize();
}
function _yesno2html(val) {
function _yesno2html (val) {
if (val) {
return '<i class="fa fa-check text-success"></i>';
} else {
@ -119,14 +119,14 @@ var CrowdSec = (function() {
}
}
function _decisionsByType(decisions) {
function _decisionsByType (decisions) {
var dectypes = {};
if (!decisions) {
return '';
}
decisions.map(function(decision) {
decisions.map(function (decision) {
// TODO ignore negative expiration?
dectypes[decision.type] = dectypes[decision.type] ? (dectypes[decision.type]+1) : 1;
dectypes[decision.type] = dectypes[decision.type] ? (dectypes[decision.type] + 1) : 1;
});
var ret = '';
for (var type in dectypes) {
@ -138,47 +138,47 @@ var CrowdSec = (function() {
return ret;
}
function _initService() {
function _initService () {
$.ajax({
url: '/api/crowdsec/service/status',
cache: false
}).done(function(data) {
}).done(function (data) {
// TODO handle errors
var crowdsec_status = data['crowdsec-status'];
if (crowdsec_status === 'unknown') {
crowdsec_status = '<span class="text-danger">Unknown</span>';
var crowdsecStatus = data['crowdsec-status'];
if (crowdsecStatus === 'unknown') {
crowdsecStatus = '<span class="text-danger">Unknown</span>';
} else {
crowdsec_status = _yesno2html(crowdsec_status === 'running');
crowdsecStatus = _yesno2html(crowdsecStatus === 'running');
}
$('#crowdsec-status').html(crowdsec_status);
$('#crowdsec-status').html(crowdsecStatus);
var crowdsec_firewall_status = data['crowdsec-firewall-status'];
if (crowdsec_firewall_status === 'unknown') {
crowdsec_firewall_status = '<span class="text-danger">Unknown</span>';
var crowdsecFirewallStatus = data['crowdsec-firewall-status'];
if (crowdsecFirewallStatus === 'unknown') {
crowdsecFirewallStatus = '<span class="text-danger">Unknown</span>';
} else {
crowdsec_firewall_status = _yesno2html(crowdsec_firewall_status === 'running');
crowdsecFirewallStatus = _yesno2html(crowdsecFirewallStatus === 'running');
}
$('#crowdsec-firewall-status').html(crowdsec_firewall_status);
$('#crowdsec-firewall-status').html(crowdsecFirewallStatus);
});
}
function _initDebug() {
function _initDebug () {
$.ajax({
url: '/api/crowdsec/service/debug',
cache: false
}).done(function(data) {
}).done(function (data) {
$('#debug pre').text(data.message);
});
}
function _initTab(selector, url, dataCallback) {
function _initTab (selector, url, dataCallback) {
var $tab = $(selector);
if ($tab.find('table.bootgrid-table').length) {
return;
}
$tab.find('table').
on("initialized.rs.jquery.bootgrid", function() {
$(_refresh_template).on('click', function() {
on('initialized.rs.jquery.bootgrid', function () {
$(_refreshTemplate).on('click', function () {
_refreshTab(selector, url, dataCallback);
}).insertBefore($tab.find('.actionBar .actions .dropdown:first'));
_addFreshness(selector);
@ -190,7 +190,7 @@ var CrowdSec = (function() {
});
}
function _refreshTab(selector, url, dataCallback) {
function _refreshTab (selector, url, dataCallback) {
$.ajax({
url: url,
cache: false
@ -198,17 +198,17 @@ var CrowdSec = (function() {
_updateFreshness(selector, moment());
}
function _initMachines() {
function _initMachines () {
var url = '/api/crowdsec/machines/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.map(function(row) {
data.map(function (row) {
rows.push({
name: row.machineId,
ip_address: row.ipAddress || ' ',
name: row.machineId,
ip_address: row.ipAddress || ' ',
last_update: row.updated_at || ' ',
validated: row.isValidated,
version: row.version || ' '
validated: row.isValidated,
version: row.version || ' '
});
});
$('#machines table').bootgrid('clear').bootgrid('append', rows);
@ -216,16 +216,16 @@ var CrowdSec = (function() {
_initTab('#machines', url, dataCallback);
}
function _initCollections() {
function _initCollections () {
var url = '/api/crowdsec/collections/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.collections.map(function(row) {
data.collections.map(function (row) {
rows.push({
name: row.name,
status: row.status,
name: row.name,
status: row.status,
local_version: row.local_version || ' ',
local_path: row.local_path || ' '
local_path: row.local_path || ' '
});
});
$('#collections table').bootgrid('clear').bootgrid('append', rows);
@ -233,17 +233,17 @@ var CrowdSec = (function() {
_initTab('#collections', url, dataCallback);
}
function _initScenarios() {
function _initScenarios () {
var url = '/api/crowdsec/scenarios/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.scenarios.map(function(row) {
data.scenarios.map(function (row) {
rows.push({
name: row.name,
status: row.status,
name: row.name,
status: row.status,
local_version: row.local_version || ' ',
local_path: row.local_path || ' ',
description: row.description || ' '
local_path: row.local_path || ' ',
description: row.description || ' '
});
});
$('#scenarios table').bootgrid('clear').bootgrid('append', rows);
@ -251,17 +251,17 @@ var CrowdSec = (function() {
_initTab('#scenarios', url, dataCallback);
}
function _initParsers() {
function _initParsers () {
var url = '/api/crowdsec/parsers/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.parsers.map(function(row) {
data.parsers.map(function (row) {
rows.push({
name: row.name,
status: row.status,
name: row.name,
status: row.status,
local_version: row.local_version || ' ',
local_path: row.local_path || ' ',
description: row.description || ' '
local_path: row.local_path || ' ',
description: row.description || ' '
});
});
$('#parsers table').bootgrid('clear').bootgrid('append', rows);
@ -269,17 +269,17 @@ var CrowdSec = (function() {
_initTab('#parsers ', url, dataCallback);
}
function _initPostoverflows() {
function _initPostoverflows () {
var url = '/api/crowdsec/postoverflows/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.postoverflows.map(function(row) {
data.postoverflows.map(function (row) {
rows.push({
name: row.name,
status: row.status,
name: row.name,
status: row.status,
local_version: row.local_version || ' ',
local_path: row.local_path || ' ',
description: row.description || ' '
local_path: row.local_path || ' ',
description: row.description || ' '
});
});
$('#postoverflows table').bootgrid('clear').bootgrid('append', rows);
@ -287,19 +287,19 @@ var CrowdSec = (function() {
_initTab('#postoverflows ', url, dataCallback);
}
function _initBouncers() {
function _initBouncers () {
var url = '/api/crowdsec/bouncers/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.map(function(row) {
data.map(function (row) {
// TODO - remove || ' ' later, it was fixed for 1.3.3
rows.push({
name: row.name,
name: row.name,
ip_address: row.ip_address || ' ',
valid: row.revoked ? false : true,
last_pull: row.last_pull,
type: row.type || ' ',
version: row.version || ' '
valid: row.revoked ? false : true,
last_pull: row.last_pull,
type: row.type || ' ',
version: row.version || ' '
});
});
$('#bouncers table').bootgrid('clear').bootgrid('append', rows);
@ -307,18 +307,18 @@ var CrowdSec = (function() {
_initTab('#bouncers ', url, dataCallback);
}
function _initAlerts() {
function _initAlerts () {
var url = '/api/crowdsec/alerts/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.map(function(row) {
data.map(function (row) {
rows.push({
id: row.id,
value: row.source.scope + (row.source.value?(':'+row.source.value):''),
reason: row.scenario || ' ',
country: row.source.cn || ' ',
as: row.source.as_name || ' ',
decisions: _decisionsByType(row.decisions) || ' ',
id: row.id,
value: row.source.scope + (row.source.value ? (':' + row.source.value) : ''),
reason: row.scenario || ' ',
country: row.source.cn || ' ',
as: row.source.as_name || ' ',
decisions: _decisionsByType(row.decisions) || ' ',
created_at: row.created_at
});
});
@ -327,30 +327,30 @@ var CrowdSec = (function() {
_initTab('#alerts ', url, dataCallback);
}
function _initDecisions() {
function _initDecisions () {
var url = '/api/crowdsec/decisions/get';
var dataCallback = function(data) {
var dataCallback = function (data) {
var rows = [];
data.map(function(row) {
row.decisions.map(function(decision) {
data.map(function (row) {
row.decisions.map(function (decision) {
// ignore deleted decisions
if (decision.duration.startsWith('-')) {
return;
}
rows.push({
// search will break on empty values when using .append(). so we use spaces
delete: '',
id: decision.id,
source: decision.origin || ' ',
scope_value: decision.scope + (decision.value?(':'+decision.value):''),
reason: decision.scenario || ' ',
action: decision.type || ' ',
country: row.source.cn || ' ',
as: row.source.as_name || ' ',
delete: '',
id: decision.id,
source: decision.origin || ' ',
scope_value: decision.scope + (decision.value ? (':' + decision.value) : ''),
reason: decision.scenario || ' ',
action: decision.type || ' ',
country: row.source.cn || ' ',
as: row.source.as_name || ' ',
events_count: row.events_count,
// XXX pre-parse duration to seconds, and integer type, for sorting
expiration: decision.duration || ' ',
alert_id: row.id || ' '
expiration: decision.duration || ' ',
alert_id: row.id || ' '
});
});
});
@ -359,16 +359,16 @@ var CrowdSec = (function() {
_initTab('#decisions ', url, dataCallback);
}
function deleteDecision(decisionId) {
function deleteDecision (decisionId) {
var $modal = $('#delete-decision-modal');
$modal.find('.modal-title').text('Delete decision #' + decisionId);
$modal.find('.modal-body').text('Are you sure?');
$modal.find('#delete-decision-confirm').on('click', function() {
$modal.find('#delete-decision-confirm').on('click', function () {
$.ajax({
// XXX handle errors
url: '/api/crowdsec/decisions/delete/' + decisionId,
type: 'DELETE',
success: function(result) {
success: function (result) {
if (result && result.message === 'OK') {
$('#decisions table').bootgrid('remove', [decisionId]);
$modal.modal('hide');
@ -379,7 +379,7 @@ var CrowdSec = (function() {
$modal.modal('show');
}
function init() {
function init () {
_initService();
$('#machines_tab').on('click', _initMachines);
@ -395,14 +395,14 @@ var CrowdSec = (function() {
if (window.location.hash) {
// activate a tab from the hash, if it exists
$(window.location.hash+'_tab').click();
$(window.location.hash + '_tab').click();
} else {
// otherwise, machines
$('#machines_tab').click();
}
$(window).on('hashchange', function(e) {
$(window.location.hash+'_tab').click();
$(window).on('hashchange', function (e) {
$(window.location.hash + '_tab').click();
});
if (new URLSearchParams(window.location.search).has('debug')) {
@ -410,8 +410,8 @@ var CrowdSec = (function() {
}
// navigation
if(window.location.hash != "") {
$('a[href="' + window.location.hash + '"]').click()
if (window.location.hash !== '') {
$('a[href="' + window.location.hash + '"]').click();
}
$('.nav-tabs a').on('shown.bs.tab', function (e) {
history.pushState(null, null, e.target.hash);
@ -422,5 +422,4 @@ var CrowdSec = (function() {
deleteDecision: deleteDecision,
init: init
};
}());