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:
@@ -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([
|
||||
|
||||
Reference in New Issue
Block a user