fix: enhance firewall rule handling with improved payload structure and error logging

This commit is contained in:
2025-12-18 08:52:53 -05:00
parent 6f5a66bea6
commit 5fbff576af

View File

@@ -660,74 +660,110 @@ class Firewall extends Component
$this->loading = true; $this->loading = true;
try { try {
// Build the payload according to Proxmox API requirements
$payload = [ $payload = [
'action' => $this->ruleAction, 'action' => strtoupper($this->ruleAction), // Ensure uppercase (ACCEPT, REJECT, DROP)
'type' => $this->ruleType, 'type' => $this->ruleType, // 'in' or 'out'
'enable' => $this->ruleEnable ? 1 : 0, 'enable' => $this->ruleEnable ? 1 : 0,
]; ];
// Note: ruleMacro is only used for UI convenience to auto-populate fields // Add optional fields only if they have values
// It is NOT sent to Proxmox API - only the actual proto/dport values are sent // Proxmox API is strict about empty values
if (!empty($this->ruleIface)) {
if (!empty(trim($this->ruleIface))) {
$payload['iface'] = trim($this->ruleIface); $payload['iface'] = trim($this->ruleIface);
} }
if (!empty(trim($this->ruleSource))) { if (!empty($this->ruleSource)) {
$payload['source'] = trim($this->ruleSource); $payload['source'] = trim($this->ruleSource);
} }
if (!empty(trim($this->ruleDest))) { if (!empty($this->ruleDest)) {
$payload['dest'] = trim($this->ruleDest); $payload['dest'] = trim($this->ruleDest);
} }
if (!empty(trim($this->ruleProto))) { // Protocol must be lowercase for Proxmox API
$payload['proto'] = trim($this->ruleProto); if (!empty($this->ruleProto)) {
$payload['proto'] = strtolower(trim($this->ruleProto));
} }
if (!empty(trim($this->ruleDport))) { if (!empty($this->ruleDport)) {
$payload['dport'] = trim($this->ruleDport); $payload['dport'] = trim($this->ruleDport);
} }
if (!empty(trim($this->ruleSport))) { if (!empty($this->ruleSport)) {
$payload['sport'] = trim($this->ruleSport); $payload['sport'] = trim($this->ruleSport);
} }
if (!empty(trim($this->ruleComment))) { if (!empty($this->ruleComment)) {
$payload['comment'] = trim($this->ruleComment); $payload['comment'] = trim($this->ruleComment);
} }
if (!empty(trim($this->ruleLog)) && $this->ruleLog !== 'nolog') { if (!empty($this->ruleLog) && $this->ruleLog !== 'nolog') {
$payload['log'] = $this->ruleLog; $payload['log'] = $this->ruleLog;
} }
// Determine if we're editing an existing rule or creating a new one
if ($this->editingRuleIndex !== null && isset($this->rules[$this->editingRuleIndex])) { if ($this->editingRuleIndex !== null && isset($this->rules[$this->editingRuleIndex])) {
// EDIT EXISTING RULE
$pos = $this->rules[$this->editingRuleIndex]['pos']; $pos = $this->rules[$this->editingRuleIndex]['pos'];
$response = $this->firewallRequest( $url = '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/firewall/rules/' . $pos;
'/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/firewall/rules/' . $pos,
'put', Log::info('Updating firewall rule', [
$payload 'url' => $url,
); 'payload' => $payload,
'pos' => $pos
]);
$response = $this->firewallRequest($url, 'put', $payload);
} else { } else {
$response = $this->firewallRequest( // CREATE NEW RULE
'/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/firewall/rules', $url = '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/firewall/rules';
'post',
$payload Log::info('Creating firewall rule', [
); 'url' => $url,
'payload' => $payload
]);
$response = $this->firewallRequest($url, 'post', $payload);
} }
// Log the response for debugging
Log::info('Firewall rule API response', [
'status' => $response->status(),
'successful' => $response->successful(),
'body' => $response->body()
]);
if ($response->successful()) { if ($response->successful()) {
$this->dispatch('notify', 'Rule ' . ($this->editingRuleIndex !== null ? 'updated' : 'created') . ' successfully', 'success'); $this->dispatch('notify', 'Rule ' . ($this->editingRuleIndex !== null ? 'updated' : 'created') . ' successfully', 'success');
// Reset the form
$this->resetRuleForm(); $this->resetRuleForm();
$this->editingRuleIndex = null; $this->editingRuleIndex = null;
$this->showRuleForm = false; $this->showRuleForm = false;
// Reload rules from Proxmox to get the updated list
$this->loadFirewallRules(); $this->loadFirewallRules();
} else { } else {
$message = $response->json()['errors'][0]['message'] ?? 'Unknown error'; // Extract error message from Proxmox API response
$responseData = $response->json();
$message = $responseData['errors'][0]['message'] ?? $responseData['message'] ?? $response->body();
Log::error('Failed to save firewall rule', [
'status' => $response->status(),
'response' => $responseData,
'payload' => $payload
]);
$this->error = 'Failed to save rule: ' . $message; $this->error = 'Failed to save rule: ' . $message;
$this->showErrorModal = true; $this->showErrorModal = true;
} }
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error('Exception saving firewall rule', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
$this->error = 'Failed to save rule: ' . $e->getMessage(); $this->error = 'Failed to save rule: ' . $e->getMessage();
$this->showErrorModal = true; $this->showErrorModal = true;
} finally { } finally {