240 lines
11 KiB
Plaintext
240 lines
11 KiB
Plaintext
<% content_for :title, "New WAF Policy" %>
|
|
|
|
<div class="space-y-6">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-gray-900">New WAF Policy</h1>
|
|
<p class="mt-2 text-gray-600">Create a new firewall policy to automatically generate rules</p>
|
|
</div>
|
|
<div class="flex space-x-3">
|
|
<%= link_to "← Back to Policies", waf_policies_path,
|
|
class: "inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50" %>
|
|
</div>
|
|
</div>
|
|
|
|
<%= form_with(model: @waf_policy, local: true, class: "space-y-6") do |form| %>
|
|
<!-- Basic Information -->
|
|
<div class="bg-white shadow rounded-lg">
|
|
<div class="px-4 py-5 sm:p-6 space-y-4">
|
|
<h3 class="text-lg leading-6 font-medium text-gray-900">📋 Basic Information</h3>
|
|
|
|
<!-- Name -->
|
|
<div>
|
|
<%= form.label :name, class: "block text-sm font-medium text-gray-700" %>
|
|
<%= form.text_field :name,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
placeholder: "e.g., Block Brazil" %>
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<div>
|
|
<%= form.label :description, "Description", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= form.text_area :description, rows: 3,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
placeholder: "Explain why this policy is needed..." %>
|
|
</div>
|
|
|
|
<!-- Policy Type -->
|
|
<div>
|
|
<%= form.label :policy_type, "Policy Type", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= form.select :policy_type,
|
|
options_for_select(@policy_types.map { |type| [type.humanize, type] }, @waf_policy.policy_type),
|
|
{ prompt: "Select policy type" },
|
|
{ class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
id: "policy-type-select" } %>
|
|
</div>
|
|
|
|
<!-- Action -->
|
|
<div>
|
|
<%= form.label :action, "Action", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= form.select :action,
|
|
options_for_select(@actions.map { |action| [action.humanize, action] }, @waf_policy.action),
|
|
{ prompt: "Select action" },
|
|
{ class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
id: "action-select" } %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Targets Configuration -->
|
|
<div class="bg-white shadow rounded-lg">
|
|
<div class="px-4 py-5 sm:p-6 space-y-4">
|
|
<h3 class="text-lg leading-6 font-medium text-gray-900">🎯 Targets Configuration</h3>
|
|
|
|
<!-- Country Policy Targets -->
|
|
<div id="country-targets" class="policy-targets hidden">
|
|
<%= form.label :targets, "Countries", class: "block text-sm font-medium text-gray-700 mb-2" %>
|
|
<div data-controller="country-selector"
|
|
data-country-selector-options-value="<%= CountryHelper.all_for_select.to_json %>"
|
|
data-country-selector-placeholder-value="Search and select countries...">
|
|
<%= select_tag "waf_policy[targets][]",
|
|
options_for_select([]),
|
|
{
|
|
multiple: true,
|
|
class: "hidden",
|
|
data: { "country-selector-target": "select" }
|
|
} %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ASN Policy Targets -->
|
|
<div id="asn-targets" class="policy-targets hidden">
|
|
<%= form.label :targets, "ASN Numbers", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= text_field_tag "waf_policy[targets][]", nil,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
placeholder: "e.g., 12345, 67890" %>
|
|
<p class="text-xs text-gray-500 mt-1">Enter ASNs separated by commas</p>
|
|
</div>
|
|
|
|
<!-- Company Policy Targets -->
|
|
<div id="company-targets" class="policy-targets hidden">
|
|
<%= form.label :targets, "Companies", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= text_field_tag "waf_policy[targets][]", nil,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
placeholder: "e.g., AWS, Digital Ocean, Google Cloud" %>
|
|
<p class="text-xs text-gray-500 mt-1">Enter company names separated by commas</p>
|
|
</div>
|
|
|
|
<!-- Network Type Targets -->
|
|
<div id="network-type-targets" class="policy-targets hidden">
|
|
<%= form.label :targets, "Network Types", class: "block text-sm font-medium text-gray-700" %>
|
|
<div class="space-y-2">
|
|
<label class="flex items-center">
|
|
<%= check_box_tag "waf_policy[targets][]", "datacenter", false, class: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2" %>
|
|
<span class="text-sm text-gray-700">Datacenter IPs</span>
|
|
</label>
|
|
<label class="flex items-center">
|
|
<%= check_box_tag "waf_policy[targets][]", "proxy", false, class: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2" %>
|
|
<span class="text-sm text-gray-700">Proxy/VPN IPs</span>
|
|
</label>
|
|
<label class="flex items-center">
|
|
<%= check_box_tag "waf_policy[targets][]", "standard", false, class: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2" %>
|
|
<span class="text-sm text-gray-700">Standard ISPs</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Additional Configuration -->
|
|
<div class="bg-white shadow rounded-lg">
|
|
<div class="px-4 py-5 sm:p-6 space-y-4">
|
|
<h3 class="text-lg leading-6 font-medium text-gray-900">⚙️ Additional Configuration</h3>
|
|
|
|
<!-- Redirect Settings (for redirect action) -->
|
|
<div id="redirect-config" class="hidden space-y-3">
|
|
<div>
|
|
<%= label_tag "additional_data[redirect_url]", "Redirect URL", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= text_field_tag "additional_data[redirect_url]", nil,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
placeholder: "https://example.com/compliance" %>
|
|
</div>
|
|
<div>
|
|
<%= label_tag "additional_data[redirect_status]", "HTTP Status", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= select_tag "additional_data[redirect_status]",
|
|
options_for_select([["301 Moved Permanently", 301], ["302 Found", 302], ["307 Temporary Redirect", 307]]),
|
|
{ include_blank: true, class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" } %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Challenge Settings (for challenge action) -->
|
|
<div id="challenge-config" class="hidden space-y-3">
|
|
<div>
|
|
<%= label_tag "additional_data[challenge_type]", "Challenge Type", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= select_tag "additional_data[challenge_type]",
|
|
options_for_select([["CAPTCHA", "captcha"], ["JavaScript", "javascript"], ["Proof of Work", "proof_of_work"]]),
|
|
{ include_blank: true, class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" } %>
|
|
</div>
|
|
<div>
|
|
<%= label_tag "additional_data[challenge_message]", "Challenge Message", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= text_area_tag "additional_data[challenge_message]", nil, rows: 2,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm",
|
|
placeholder: "Please verify you are human to continue..." %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Expiration -->
|
|
<div>
|
|
<%= form.label :expires_at, "Expires At (optional)", class: "block text-sm font-medium text-gray-700" %>
|
|
<%= form.datetime_local_field :expires_at,
|
|
class: "block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" %>
|
|
<p class="text-xs text-gray-500 mt-1">Leave blank for permanent policy</p>
|
|
</div>
|
|
|
|
<!-- Enabled -->
|
|
<div class="flex items-center">
|
|
<%= form.check_box :enabled, class: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" %>
|
|
<%= form.label :enabled, "Enable this policy immediately", class: "ml-2 text-sm text-gray-700" %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Submit Buttons -->
|
|
<div class="flex justify-end space-x-3">
|
|
<%= link_to "Cancel", waf_policies_path,
|
|
class: "inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50" %>
|
|
<%= form.submit "Create Policy",
|
|
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 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const policyTypeSelect = document.getElementById('policy-type-select');
|
|
const actionSelect = document.getElementById('action-select');
|
|
const allTargets = document.querySelectorAll('.policy-targets');
|
|
const redirectConfig = document.getElementById('redirect-config');
|
|
const challengeConfig = document.getElementById('challenge-config');
|
|
|
|
function updateTargetsVisibility() {
|
|
const selectedType = policyTypeSelect.value;
|
|
|
|
// Hide all target sections
|
|
allTargets.forEach(target => target.classList.add('hidden'));
|
|
|
|
// Show relevant target section
|
|
switch(selectedType) {
|
|
case 'country':
|
|
document.getElementById('country-targets').classList.remove('hidden');
|
|
break;
|
|
case 'asn':
|
|
document.getElementById('asn-targets').classList.remove('hidden');
|
|
break;
|
|
case 'company':
|
|
document.getElementById('company-targets').classList.remove('hidden');
|
|
break;
|
|
case 'network_type':
|
|
document.getElementById('network-type-targets').classList.remove('hidden');
|
|
break;
|
|
}
|
|
}
|
|
|
|
function updateActionConfig() {
|
|
const selectedAction = actionSelect.value;
|
|
|
|
// Hide all config sections
|
|
redirectConfig.classList.add('hidden');
|
|
challengeConfig.classList.add('hidden');
|
|
|
|
// Show relevant config section
|
|
switch(selectedAction) {
|
|
case 'redirect':
|
|
redirectConfig.classList.remove('hidden');
|
|
break;
|
|
case 'challenge':
|
|
challengeConfig.classList.remove('hidden');
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Add event listeners
|
|
policyTypeSelect.addEventListener('change', updateTargetsVisibility);
|
|
actionSelect.addEventListener('change', updateActionConfig);
|
|
|
|
// Initial update
|
|
updateTargetsVisibility();
|
|
updateActionConfig();
|
|
});
|
|
</script> |