ARGUS WordPress Defence 1.0.0 — first production release
Automatic WordPress security: local firewall, malware and file-integrity scanning, vulnerability protection, quarantine, scheduled backups, an optional page cache, and automatic global threat intelligence. See README.md for installation, update, and uninstall instructions.
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class Argus_Events {
|
||||
|
||||
const DEFAULT_MAX_ROWS = 50000;
|
||||
|
||||
public static function record( $type, $severity, $summary, array $payload = array(), $ip = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->insert(
|
||||
Argus_DB::table( 'events' ),
|
||||
array(
|
||||
'event_type' => $type,
|
||||
'severity' => $severity,
|
||||
'ip' => $ip,
|
||||
'summary' => $summary,
|
||||
'payload' => wp_json_encode( $payload ),
|
||||
'created_at' => current_time( 'mysql', true ),
|
||||
),
|
||||
array( '%s', '%s', '%s', '%s', '%s', '%s' )
|
||||
);
|
||||
|
||||
return (int) $wpdb->insert_id;
|
||||
}
|
||||
|
||||
public static function recent( $limit = 50, $type = null ) {
|
||||
global $wpdb;
|
||||
$table = Argus_DB::table( 'events' );
|
||||
|
||||
if ( $type ) {
|
||||
$rows = $wpdb->get_results(
|
||||
$wpdb->prepare( "SELECT * FROM {$table} WHERE event_type = %s ORDER BY created_at DESC LIMIT %d", $type, $limit ) // phpcs:ignore
|
||||
);
|
||||
} else {
|
||||
$rows = $wpdb->get_results(
|
||||
$wpdb->prepare( "SELECT * FROM {$table} ORDER BY created_at DESC LIMIT %d", $limit ) // phpcs:ignore
|
||||
);
|
||||
}
|
||||
|
||||
foreach ( $rows as &$row ) {
|
||||
$row->payload = json_decode( $row->payload, true );
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public static function counts_since( $since_mysql ) {
|
||||
global $wpdb;
|
||||
$table = Argus_DB::table( 'events' );
|
||||
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT event_type, severity, COUNT(*) AS cnt FROM {$table} WHERE created_at >= %s GROUP BY event_type, severity", // phpcs:ignore
|
||||
$since_mysql
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const PER_PAGE = 10;
|
||||
|
||||
public static function paginated( $page = 1, array $filters = array(), $per_page = self::PER_PAGE ) {
|
||||
global $wpdb;
|
||||
$table = Argus_DB::table( 'events' );
|
||||
$page = max( 1, (int) $page );
|
||||
$offset = ( $page - 1 ) * $per_page;
|
||||
|
||||
$where = array( '1=1' );
|
||||
$args = array();
|
||||
|
||||
if ( ! empty( $filters['search'] ) ) {
|
||||
$where[] = 'summary LIKE %s';
|
||||
$args[] = '%' . $wpdb->esc_like( $filters['search'] ) . '%';
|
||||
}
|
||||
if ( ! empty( $filters['severity'] ) ) {
|
||||
$where[] = 'severity = %s';
|
||||
$args[] = $filters['severity'];
|
||||
}
|
||||
if ( ! empty( $filters['type'] ) ) {
|
||||
$where[] = 'event_type = %s';
|
||||
$args[] = $filters['type'];
|
||||
}
|
||||
if ( ! empty( $filters['since'] ) ) {
|
||||
$where[] = 'created_at >= %s';
|
||||
$args[] = $filters['since'];
|
||||
}
|
||||
|
||||
$where_sql = implode( ' AND ', $where );
|
||||
|
||||
$count_sql = "SELECT COUNT(*) FROM {$table} WHERE {$where_sql}"; // phpcs:ignore
|
||||
$total = (int) ( $args ? $wpdb->get_var( $wpdb->prepare( $count_sql, $args ) ) : $wpdb->get_var( $count_sql ) ); // phpcs:ignore
|
||||
|
||||
$list_sql = "SELECT * FROM {$table} WHERE {$where_sql} ORDER BY created_at DESC LIMIT %d OFFSET %d"; // phpcs:ignore
|
||||
$list_args = array_merge( $args, array( $per_page, $offset ) );
|
||||
$rows = $wpdb->get_results( $wpdb->prepare( $list_sql, $list_args ) ); // phpcs:ignore
|
||||
|
||||
foreach ( $rows as &$row ) {
|
||||
$row->payload = json_decode( $row->payload, true );
|
||||
}
|
||||
|
||||
return array(
|
||||
'rows' => $rows,
|
||||
'total' => $total,
|
||||
'total_pages' => max( 1, (int) ceil( $total / $per_page ) ),
|
||||
'page' => $page,
|
||||
);
|
||||
}
|
||||
|
||||
public static function distinct_types() {
|
||||
global $wpdb;
|
||||
$table = Argus_DB::table( 'events' );
|
||||
return $wpdb->get_col( "SELECT DISTINCT event_type FROM {$table} ORDER BY event_type ASC" ); // phpcs:ignore
|
||||
}
|
||||
|
||||
const RETENTION_DAYS_BY_SEVERITY = array(
|
||||
'info' => 30,
|
||||
'low' => 90,
|
||||
'medium' => 365,
|
||||
'high' => 365,
|
||||
'critical' => 365,
|
||||
);
|
||||
|
||||
public static function prune() {
|
||||
global $wpdb;
|
||||
$table = Argus_DB::table( 'events' );
|
||||
|
||||
$retention = apply_filters( 'argus_wpd_event_retention_days', self::RETENTION_DAYS_BY_SEVERITY );
|
||||
$deleted = 0;
|
||||
foreach ( $retention as $severity => $days ) {
|
||||
$cutoff = gmdate( 'Y-m-d H:i:s', time() - ( (int) $days * DAY_IN_SECONDS ) );
|
||||
$deleted += (int) $wpdb->query(
|
||||
$wpdb->prepare( "DELETE FROM {$table} WHERE severity = %s AND created_at < %s", $severity, $cutoff ) // phpcs:ignore
|
||||
);
|
||||
}
|
||||
|
||||
$max_rows = (int) apply_filters( 'argus_wpd_max_event_rows', self::DEFAULT_MAX_ROWS );
|
||||
$total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ); // phpcs:ignore
|
||||
if ( $total <= $max_rows ) {
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
$overflow = $total - $max_rows;
|
||||
$deleted += (int) $wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM {$table} ORDER BY created_at ASC LIMIT %d", // phpcs:ignore
|
||||
$overflow
|
||||
)
|
||||
);
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user