231 lines
11 KiB
Plaintext
231 lines
11 KiB
Plaintext
<% content_for :title, "WAF Policies" %>
|
|
|
|
<div class="space-y-6">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-gray-900">WAF Policies</h1>
|
|
<p class="mt-2 text-gray-600">High-level firewall policies that automatically generate rules</p>
|
|
</div>
|
|
<div class="flex space-x-3">
|
|
<%= link_to "🌍 Block Countries", new_country_waf_policies_path,
|
|
class: "inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-600 hover:bg-red-700" %>
|
|
<%= link_to "Create Policy", new_waf_policy_path,
|
|
class: "inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700" %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Statistics Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<div class="bg-white overflow-hidden shadow rounded-lg">
|
|
<div class="p-5">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<svg class="h-6 w-6 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
</div>
|
|
<div class="ml-5 w-0 flex-1">
|
|
<dl>
|
|
<dt class="text-sm font-medium text-gray-500 truncate">Total Policies</dt>
|
|
<dd class="text-lg font-medium text-gray-900"><%= number_with_delimiter(@waf_policies.count) %></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white overflow-hidden shadow rounded-lg">
|
|
<div class="p-5">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<svg class="h-6 w-6 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
</div>
|
|
<div class="ml-5 w-0 flex-1">
|
|
<dl>
|
|
<dt class="text-sm font-medium text-gray-500 truncate">Active Policies</dt>
|
|
<dd class="text-lg font-medium text-gray-900"><%= number_with_delimiter(@waf_policies.active.count) %></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white overflow-hidden shadow rounded-lg">
|
|
<div class="p-5">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<svg class="h-6 w-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
</svg>
|
|
</div>
|
|
<div class="ml-5 w-0 flex-1">
|
|
<dl>
|
|
<dt class="text-sm font-medium text-gray-500 truncate">Generated Rules</dt>
|
|
<dd class="text-lg font-medium text-gray-900">
|
|
<%= number_with_delimiter(Rule.policy_generated.count) %>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white overflow-hidden shadow rounded-lg">
|
|
<div class="p-5">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<svg class="h-6 w-6 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
|
</svg>
|
|
</div>
|
|
<div class="ml-5 w-0 flex-1">
|
|
<dl>
|
|
<dt class="text-sm font-medium text-gray-500 truncate">Deny Policies</dt>
|
|
<dd class="text-lg font-medium text-gray-900">
|
|
<%= number_with_delimiter(@waf_policies.where(action: 'deny').count) %>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Policies Table -->
|
|
<div class="bg-white shadow overflow-hidden sm:rounded-md">
|
|
<div class="px-4 py-5 sm:px-6">
|
|
<h3 class="text-lg leading-6 font-medium text-gray-900">Firewall Policies</h3>
|
|
<p class="mt-1 max-w-2xl text-sm text-gray-500">
|
|
High-level policies that automatically generate specific WAF rules when matching network ranges are discovered.
|
|
</p>
|
|
</div>
|
|
<div class="border-t border-gray-200">
|
|
<% if @waf_policies.any? %>
|
|
<ul class="divide-y divide-gray-200">
|
|
<% @waf_policies.each do |policy| %>
|
|
<li class="hover:bg-gray-50">
|
|
<div class="px-4 py-4 sm:px-6">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<% if policy.country_policy? %>
|
|
<span class="text-2xl">🌍</span>
|
|
<% elsif policy.asn_policy? %>
|
|
<span class="text-2xl">🏢</span>
|
|
<% elsif policy.company_policy? %>
|
|
<span class="text-2xl">🏭</span>
|
|
<% elsif policy.network_type_policy? %>
|
|
<span class="text-2xl">🌐</span>
|
|
<% end %>
|
|
</div>
|
|
<div class="ml-4">
|
|
<div class="flex items-center">
|
|
<%= link_to policy.name, waf_policy_path(policy),
|
|
class: "text-sm font-medium text-gray-900 hover:text-blue-600" %>
|
|
|
|
<!-- Status Badge -->
|
|
<% if policy.active? %>
|
|
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
|
|
Active
|
|
</span>
|
|
<% else %>
|
|
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
|
Inactive
|
|
</span>
|
|
<% end %>
|
|
|
|
<!-- Action Badge -->
|
|
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium
|
|
<%= case policy.action
|
|
when 'deny' then 'bg-red-100 text-red-800'
|
|
when 'allow' then 'bg-green-100 text-green-800'
|
|
when 'redirect' then 'bg-yellow-100 text-yellow-800'
|
|
when 'challenge' then 'bg-purple-100 text-purple-800'
|
|
end %>">
|
|
<%= policy.action.upcase %>
|
|
</span>
|
|
</div>
|
|
<div class="mt-1 text-sm text-gray-500">
|
|
<%= policy.policy_type.humanize %> policy targeting
|
|
<% if policy.targets.length > 3 %>
|
|
<%= policy.targets.length %> items
|
|
<% else %>
|
|
<%= policy.targets.join(', ') %>
|
|
<% end %>
|
|
• <%= policy.generated_rules_count %> rules generated
|
|
</div>
|
|
<% if policy.description.present? %>
|
|
<div class="mt-1 text-sm text-gray-600">
|
|
<%= policy.description %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<%= link_to "View", waf_policy_path(policy),
|
|
class: "inline-flex items-center px-3 py-1 border border-gray-300 shadow-sm text-xs font-medium rounded text-gray-700 bg-white hover:bg-gray-50" %>
|
|
|
|
<% if policy.active? %>
|
|
<%= link_to "Deactivate", deactivate_waf_policy_path(policy),
|
|
method: :post,
|
|
data: { confirm: "Are you sure you want to deactivate this policy?" },
|
|
class: "inline-flex items-center px-3 py-1 border border-gray-300 shadow-sm text-xs font-medium rounded text-gray-700 bg-white hover:bg-gray-50" %>
|
|
<% else %>
|
|
<%= link_to "Activate", activate_waf_policy_path(policy),
|
|
method: :post,
|
|
class: "inline-flex items-center px-3 py-1 border border-transparent shadow-sm text-xs font-medium rounded text-white bg-green-600 hover:bg-green-700" %>
|
|
<% end %>
|
|
|
|
<%= link_to "Edit", edit_waf_policy_path(policy),
|
|
class: "inline-flex items-center px-3 py-1 border border-gray-300 shadow-sm text-xs font-medium rounded text-gray-700 bg-white hover:bg-gray-50" %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<% end %>
|
|
</ul>
|
|
<% else %>
|
|
<div class="text-center py-12">
|
|
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
</svg>
|
|
<h3 class="mt-2 text-sm font-medium text-gray-900">No policies</h3>
|
|
<p class="mt-1 text-sm text-gray-500">Get started by creating your first WAF policy.</p>
|
|
<div class="mt-6">
|
|
<%= link_to "Create Policy", new_waf_policy_path,
|
|
class: "inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700" %>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
<% if @waf_policies.respond_to?(:total_pages) && @waf_policies.total_pages > 1 %>
|
|
<div class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6">
|
|
<div class="flex-1 flex justify-between sm:hidden">
|
|
<%= link_to_previous_page @waf_policies, "Previous", class: "relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50" %>
|
|
<%= link_to_next_page @waf_policies, "Next", class: "ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50" %>
|
|
</div>
|
|
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
|
<div>
|
|
<p class="text-sm text-gray-700">
|
|
Showing
|
|
<span class="font-medium"><%= (@waf_policies.current_page - 1) * @waf_policies.limit_value + 1 %></span>
|
|
to
|
|
<span class="font-medium"><%= [@waf_policies.current_page * @waf_policies.limit_value, @waf_policies.total_count].min %></span>
|
|
of
|
|
<span class="font-medium"><%= number_with_delimiter(@waf_policies.total_count) %></span>
|
|
results
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<%== pagy_nav(@pagy) %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div> |