Files
honeydany/app/templates/threat_rules.html
T

374 lines
14 KiB
HTML

{{ define "threat_rules_title" }}Threat Rules{{ end }}
{{ define "threat_rules_content" }}
<div class="space-y-6">
<div class="flex justify-between items-center">
<h1 class="text-2xl font-semibold text-white">Threat Detection Rules</h1>
<button id="add-rule-btn" class="px-4 py-2 bg-primary-600 hover:bg-primary-500 rounded text-white">
Add New Rule
</button>
</div>
<!-- Rules Table -->
<div class="bg-gray-800 border border-gray-700 rounded-lg">
<div class="p-4 border-b border-gray-700">
<h2 class="text-lg font-semibold text-white">Active Rules</h2>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-700">
<thead class="bg-gray-800">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Name</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Service</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Condition</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Threshold</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Time Window</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Action</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Status</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody id="rules-table" class="bg-gray-900 divide-y divide-gray-800">
<!-- Dynamic content will be inserted here -->
</tbody>
</table>
</div>
</div>
<!-- Rule Form Modal -->
<div id="rule-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-gray-800 rounded-lg max-w-2xl w-full">
<div class="p-4 border-b border-gray-700 flex justify-between items-center">
<h3 id="modal-title" class="text-lg font-semibold text-white">Add New Rule</h3>
<button id="close-modal" class="text-gray-400 hover:text-white">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<form id="rule-form" class="p-4 space-y-4">
<input type="hidden" id="rule-id" name="id">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm text-gray-300 mb-1">Rule Name</label>
<input type="text" id="rule-name" name="name" required
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100"
placeholder="e.g., SSH Brute Force Detection">
</div>
<div>
<label class="block text-sm text-gray-300 mb-1">Service</label>
<select id="rule-service" name="service" required
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100">
<option value="*">All Services</option>
<option value="ssh">SSH</option>
<option value="http">HTTP</option>
<option value="https">HTTPS</option>
<option value="ftp">FTP</option>
<option value="smtp">SMTP</option>
<option value="imap">IMAP</option>
<option value="telnet">Telnet</option>
<option value="mysql">MySQL</option>
<option value="postgresql">PostgreSQL</option>
<option value="mongodb">MongoDB</option>
<option value="rdp">RDP</option>
<option value="smb">SMB</option>
<option value="sip">SIP</option>
<option value="vnc">VNC</option>
</select>
</div>
</div>
<div>
<label class="block text-sm text-gray-300 mb-1">Description</label>
<textarea id="rule-description" name="description" rows="2"
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100"
placeholder="Describe what this rule detects..."></textarea>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label class="block text-sm text-gray-300 mb-1">Condition</label>
<select id="rule-condition" name="condition" required
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100">
<option value="connection_count">Connection Count</option>
<option value="auth_attempts">Authentication Attempts</option>
<option value="service_diversity">Service Diversity</option>
</select>
</div>
<div>
<label class="block text-sm text-gray-300 mb-1">Threshold</label>
<input type="number" id="rule-threshold" name="threshold" required min="1"
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100"
placeholder="e.g., 10">
</div>
<div>
<label class="block text-sm text-gray-300 mb-1">Time Window (minutes)</label>
<input type="number" id="rule-time-window" name="time_window" required min="1"
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100"
placeholder="e.g., 60">
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm text-gray-300 mb-1">Action</label>
<select id="rule-action" name="action" required
class="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-gray-100">
<option value="alert">Alert Only</option>
<option value="block">Block IP</option>
<option value="monitor">Monitor</option>
</select>
</div>
<div class="flex items-center">
<label class="flex items-center text-sm text-gray-300">
<input type="checkbox" id="rule-enabled" name="enabled" checked
class="mr-2 h-4 w-4 text-primary-600 bg-gray-900 border-gray-700 rounded">
Rule Enabled
</label>
</div>
</div>
<div class="flex justify-end space-x-3 pt-4">
<button type="button" id="cancel-btn" class="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded text-white">
Cancel
</button>
<button type="submit" class="px-4 py-2 bg-primary-600 hover:bg-primary-500 rounded text-white">
Save Rule
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
let currentRules = [];
let editingRuleId = null;
// Load initial data
document.addEventListener('DOMContentLoaded', function() {
loadRules();
});
// Event listeners
document.getElementById('add-rule-btn').addEventListener('click', function() {
showRuleModal();
});
document.getElementById('close-modal').addEventListener('click', hideRuleModal);
document.getElementById('cancel-btn').addEventListener('click', hideRuleModal);
document.getElementById('rule-form').addEventListener('submit', function(e) {
e.preventDefault();
saveRule();
});
// Load threat rules
async function loadRules() {
try {
const response = await fetch('/api/threat/rules');
const data = await response.json();
currentRules = data.rules || [];
renderRulesTable(currentRules);
} catch (error) {
console.error('Failed to load rules:', error);
}
}
// Render rules table
function renderRulesTable(rules) {
const tbody = document.getElementById('rules-table');
tbody.innerHTML = '';
if (rules.length === 0) {
tbody.innerHTML = '<tr><td colspan="8" class="px-4 py-4 text-center text-gray-400">No rules configured</td></tr>';
return;
}
rules.forEach(rule => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-800';
const statusBadge = rule.enabled
? '<span class="px-2 py-1 text-xs bg-green-600 text-white rounded">Enabled</span>'
: '<span class="px-2 py-1 text-xs bg-gray-600 text-white rounded">Disabled</span>';
const actionBadge = getActionBadge(rule.action);
row.innerHTML = `
<td class="px-4 py-2 text-sm text-gray-300">
<div class="font-medium">${rule.name}</div>
<div class="text-xs text-gray-500">${rule.description || ''}</div>
</td>
<td class="px-4 py-2 text-sm text-gray-300">
<span class="px-2 py-1 text-xs bg-gray-700 text-gray-300 rounded">${rule.service}</span>
</td>
<td class="px-4 py-2 text-sm text-gray-300">${rule.condition}</td>
<td class="px-4 py-2 text-sm text-gray-300">${rule.threshold}</td>
<td class="px-4 py-2 text-sm text-gray-300">${rule.time_window}m</td>
<td class="px-4 py-2 text-sm">${actionBadge}</td>
<td class="px-4 py-2 text-sm">${statusBadge}</td>
<td class="px-4 py-2 text-sm">
<div class="flex space-x-2">
<button onclick="editRule(${rule.id})" class="px-2 py-1 text-xs bg-blue-600 hover:bg-blue-500 text-white rounded">Edit</button>
<button onclick="toggleRule(${rule.id}, ${!rule.enabled})" class="px-2 py-1 text-xs ${rule.enabled ? 'bg-gray-600 hover:bg-gray-500' : 'bg-green-600 hover:bg-green-500'} text-white rounded">
${rule.enabled ? 'Disable' : 'Enable'}
</button>
<button onclick="deleteRule(${rule.id})" class="px-2 py-1 text-xs bg-red-600 hover:bg-red-500 text-white rounded">Delete</button>
</div>
</td>
`;
tbody.appendChild(row);
});
}
// Get action badge HTML
function getActionBadge(action) {
switch (action) {
case 'block':
return '<span class="px-2 py-1 text-xs bg-red-600 text-white rounded">Block</span>';
case 'alert':
return '<span class="px-2 py-1 text-xs bg-yellow-600 text-white rounded">Alert</span>';
case 'monitor':
return '<span class="px-2 py-1 text-xs bg-blue-600 text-white rounded">Monitor</span>';
default:
return '<span class="px-2 py-1 text-xs bg-gray-600 text-white rounded">Unknown</span>';
}
}
// Show rule modal
function showRuleModal(rule = null) {
editingRuleId = rule ? rule.id : null;
if (rule) {
document.getElementById('modal-title').textContent = 'Edit Rule';
document.getElementById('rule-id').value = rule.id;
document.getElementById('rule-name').value = rule.name;
document.getElementById('rule-description').value = rule.description || '';
document.getElementById('rule-service').value = rule.service;
document.getElementById('rule-condition').value = rule.condition;
document.getElementById('rule-threshold').value = rule.threshold;
document.getElementById('rule-time-window').value = rule.time_window;
document.getElementById('rule-action').value = rule.action;
document.getElementById('rule-enabled').checked = rule.enabled;
} else {
document.getElementById('modal-title').textContent = 'Add New Rule';
document.getElementById('rule-form').reset();
document.getElementById('rule-enabled').checked = true;
}
document.getElementById('rule-modal').classList.remove('hidden');
}
// Hide rule modal
function hideRuleModal() {
document.getElementById('rule-modal').classList.add('hidden');
editingRuleId = null;
}
// Save rule
async function saveRule() {
const formData = new FormData(document.getElementById('rule-form'));
const ruleData = {
name: formData.get('name'),
description: formData.get('description'),
service: formData.get('service'),
condition: formData.get('condition'),
threshold: parseInt(formData.get('threshold')),
time_window: parseInt(formData.get('time_window')),
action: formData.get('action'),
enabled: formData.has('enabled')
};
try {
let response;
if (editingRuleId) {
// Update existing rule
response = await fetch(`/api/threat/rules/${editingRuleId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(ruleData)
});
} else {
// Create new rule
response = await fetch('/api/threat/rules', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(ruleData)
});
}
if (response.ok) {
hideRuleModal();
loadRules();
} else {
const error = await response.text();
alert(`Failed to save rule: ${error}`);
}
} catch (error) {
console.error('Failed to save rule:', error);
alert('Failed to save rule');
}
}
// Edit rule
function editRule(ruleId) {
const rule = currentRules.find(r => r.id === ruleId);
if (rule) {
showRuleModal(rule);
}
}
// Toggle rule enabled/disabled
async function toggleRule(ruleId, enabled) {
const rule = currentRules.find(r => r.id === ruleId);
if (!rule) return;
const updatedRule = { ...rule, enabled: enabled };
try {
const response = await fetch(`/api/threat/rules/${ruleId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updatedRule)
});
if (response.ok) {
loadRules();
} else {
alert('Failed to update rule');
}
} catch (error) {
console.error('Failed to toggle rule:', error);
alert('Failed to update rule');
}
}
// Delete rule
async function deleteRule(ruleId) {
const rule = currentRules.find(r => r.id === ruleId);
if (!rule) return;
if (!confirm(`Are you sure you want to delete the rule "${rule.name}"?`)) return;
try {
const response = await fetch(`/api/threat/rules/${ruleId}`, {
method: 'DELETE'
});
if (response.ok) {
loadRules();
} else {
alert('Failed to delete rule');
}
} catch (error) {
console.error('Failed to delete rule:', error);
alert('Failed to delete rule');
}
}
</script>
{{ end }}