feat: implement network adapter management in Proxmox Firewall component, allowing users to enable or disable firewalls for individual adapters and enhancing overall functionality

This commit is contained in:
2025-12-01 13:57:36 -05:00
parent 3e89d0c847
commit aa4115732e
2 changed files with 262 additions and 6 deletions

View File

@@ -17,13 +17,15 @@ class Firewall extends Component
public string $error = '';
public bool $showErrorModal = false;
public bool $showRuleForm = false;
public array $networkAdapters = [];
public array $adapterFirewallStates = [];
// Rule creation/editing
public ?int $editingRulePos = null;
public string $ruleAction = 'ACCEPT';
public string $ruleSource = '';
public string $ruleDest = '';
public string $ruleProto = '';
public string $ruleProto = 'tcp';
public string $ruleDport = '';
public string $ruleSport = '';
public string $ruleComment = '';
@@ -44,10 +46,12 @@ class Firewall extends Component
public function mount(Server $server): void
{
parent::mount($server);
$this->server->loadMissing('ipAddresses');
$this->loadFirewallOptions();
$this->loadFirewallRules();
$this->loadAliases();
$this->loadIpsets();
$this->loadNetworkAdapters();
}
/**
@@ -217,7 +221,7 @@ class Firewall extends Component
$this->ruleAction = 'ACCEPT';
$this->ruleSource = '';
$this->ruleDest = '';
$this->ruleProto = '';
$this->ruleProto = 'tcp';
$this->ruleDport = '';
$this->ruleSport = '';
$this->ruleComment = '';
@@ -557,6 +561,132 @@ class Firewall extends Component
}
}
public function loadNetworkAdapters(): void
{
try {
$proxmox = new Proxmox;
$config = $proxmox->request('/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config')->json()['data'] ?? [];
$this->networkAdapters = [];
$this->adapterFirewallStates = [];
foreach ($config as $key => $value) {
if (!is_string($key) || !str_starts_with($key, 'net')) {
continue;
}
$configString = (string) $value;
$segments = array_filter(array_map('trim', explode(',', $configString)));
$model = 'virtio';
$mac = null;
$bridge = null;
$firewallEnabled = false;
foreach ($segments as $segment) {
if (!str_contains($segment, '=')) {
continue;
}
[$segmentKey, $segmentValue] = array_map('trim', explode('=', $segment, 2));
$segmentKeyLower = strtolower($segmentKey);
if (in_array($segmentKeyLower, ['virtio', 'e1000', 'e1000e', 'rtl8139', 'vmxnet3', 'pcnet'], true)) {
$model = $segmentKeyLower;
$mac = $segmentValue;
} elseif ($segmentKeyLower === 'bridge') {
$bridge = $segmentValue;
} elseif ($segmentKeyLower === 'firewall') {
$firewallEnabled = ($segmentValue == '1' || $segmentValue === '1');
}
}
$this->networkAdapters[$key] = [
'name' => $key,
'model' => $model,
'mac' => $mac,
'bridge' => $bridge,
];
$this->adapterFirewallStates[$key] = $firewallEnabled;
}
} catch (\Exception $e) {
$this->networkAdapters = [];
$this->adapterFirewallStates = [];
}
}
public function toggleAdapterFirewall(string $adapterName): void
{
$this->loading = true;
try {
$proxmox = new Proxmox;
$config = $proxmox->request('/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config')->json()['data'] ?? [];
if (!isset($config[$adapterName])) {
$this->error = 'Network adapter not found: ' . $adapterName;
$this->showErrorModal = true;
$this->loading = false;
return;
}
$currentConfig = (string) $config[$adapterName];
$segments = array_filter(array_map('trim', explode(',', $currentConfig)));
$newSegments = [];
$firewallFound = false;
$currentFirewallState = $this->adapterFirewallStates[$adapterName] ?? false;
$newFirewallState = !$currentFirewallState;
foreach ($segments as $segment) {
if (!str_contains($segment, '=')) {
$newSegments[] = $segment;
continue;
}
[$segmentKey, $segmentValue] = array_map('trim', explode('=', $segment, 2));
if (strtolower($segmentKey) === 'firewall') {
$firewallFound = true;
if ($newFirewallState) {
$newSegments[] = 'firewall=1';
}
// If disabling, we skip adding firewall=1, effectively removing it
} else {
$newSegments[] = $segment;
}
}
// If firewall wasn't in the config and we're enabling it, add it
if (!$firewallFound && $newFirewallState) {
$newSegments[] = 'firewall=1';
}
$newConfig = implode(',', $newSegments);
$proxmox->request(
'/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config',
'put',
[$adapterName => $newConfig]
);
$this->adapterFirewallStates[$adapterName] = $newFirewallState;
$this->notify('Firewall ' . ($newFirewallState ? 'enabled' : 'disabled') . ' for ' . $adapterName, 'success');
$this->loadNetworkAdapters(); // Reload to ensure consistency
} catch (\Exception $e) {
$errorMessage = $e->getMessage();
if (method_exists($e, 'response') && $e->response()) {
$errorData = $e->response()->json();
if (isset($errorData['errors']) && is_array($errorData['errors']) && !empty($errorData['errors'])) {
$errorMessage = $errorData['errors'][0]['message'] ?? $errorMessage;
} elseif (isset($errorData['message'])) {
$errorMessage = $errorData['message'];
}
}
$this->error = 'Failed to toggle firewall for adapter: ' . $errorMessage;
$this->showErrorModal = true;
} finally {
$this->loading = false;
}
}
public function render()
{
return view('proxmox::firewall')->layoutData([