diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml
deleted file mode 100644
index 4f02240..0000000
--- a/.github/workflows/build-and-release.yml
+++ /dev/null
@@ -1,126 +0,0 @@
-name: Build and Release
-
-on:
- push:
- branches: [ main ]
- paths-ignore:
- - '**.md'
- - 'docs/**'
- - '.github/**'
- - '!.github/workflows/build-and-release.yml'
- pull_request:
- branches: [ main ]
- workflow_dispatch:
- inputs:
- release:
- description: 'Create a release'
- required: false
- default: false
- type: boolean
-
-jobs:
- build:
- runs-on: windows-latest
-
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0
-
- - name: Setup .NET
- uses: actions/setup-dotnet@v3
- with:
- dotnet-version: '6.0.x'
-
- - name: Setup PowerShell
- uses: actions/setup-powershell@v1
- with:
- powershell-version: '7.2'
-
- - name: Restore dependencies
- run: dotnet restore src/PSOPNSenseAPI.sln
-
- - name: Run tests
- run: pwsh -Command "./build/test.ps1 -Configuration Release"
-
- - name: Build and package
- run: |
- pwsh -Command "./build/build-release.ps1 -Clean -Package"
-
- - name: Upload build artifacts
- uses: actions/upload-artifact@v3
- with:
- name: PSOPNSenseAPI
- path: output/PSOPNSenseAPI/
-
- - name: Upload package artifacts
- uses: actions/upload-artifact@v3
- with:
- name: PSOPNSenseAPI-Package
- path: packages/*.zip
-
- release:
- needs: build
- if: github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event.inputs.release == 'true'
- runs-on: windows-latest
-
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0
-
- - name: Setup PowerShell
- uses: actions/setup-powershell@v1
- with:
- powershell-version: '7.2'
-
- - name: Download build artifacts
- uses: actions/download-artifact@v3
- with:
- name: PSOPNSenseAPI
- path: output/PSOPNSenseAPI/
-
- - name: Download package artifacts
- uses: actions/download-artifact@v3
- with:
- name: PSOPNSenseAPI-Package
- path: packages/
-
- - name: Configure Git
- run: |
- git config --global user.name "GitHub Actions"
- git config --global user.email "actions@github.com"
-
- - name: Create Release
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- $version = Get-Date -Format "yyyy.MM.dd.HHmm"
-
- # Update version in project file
- $projectFile = "src/PSOPNSenseAPI/PSOPNSenseAPI.csproj"
- $projectXml = [xml](Get-Content $projectFile)
- $versionNode = $projectXml.Project.PropertyGroup.Version
- $versionNode.InnerText = $version
- $projectXml.Save($projectFile)
-
- # Update version in module manifest
- $manifestFile = "PSOPNSenseAPI/PSOPNSenseAPI.psd1"
- $manifestContent = Get-Content -Path $manifestFile -Raw
- $manifestContent = $manifestContent -replace "ModuleVersion\s*=\s*['`"].*['`"]", "ModuleVersion = '$version'"
- Set-Content -Path $manifestFile -Value $manifestContent
-
- # Commit changes
- git add $projectFile
- git add $manifestFile
- git commit -m "Release version $version [skip ci]"
- git push
-
- # Create release
- $packagePath = Get-ChildItem -Path "packages/*.zip" | Select-Object -First 1 -ExpandProperty FullName
-
- gh release create "v$version" `
- --title "Release v$version" `
- --notes "Release version $version - $(Get-Date -Format 'yyyy-MM-dd')" `
- $packagePath
- shell: pwsh
diff --git a/.gitignore b/.gitignore
index 4b82ccd..0fdfa7c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
.vs/
bin/
obj/
+*.zip
+output/*.zip
diff --git a/output/PSOPNSenseAPI-v0.6.0-updated.zip b/output/PSOPNSenseAPI-v0.6.0-updated.zip
deleted file mode 100644
index bf466c3..0000000
Binary files a/output/PSOPNSenseAPI-v0.6.0-updated.zip and /dev/null differ
diff --git a/output/PSOPNSenseAPI-v0.6.0.zip b/output/PSOPNSenseAPI-v0.6.0.zip
deleted file mode 100644
index b38cfe6..0000000
Binary files a/output/PSOPNSenseAPI-v0.6.0.zip and /dev/null differ
diff --git a/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1 b/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1
index 4535f60..7deaec1 100644
--- a/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1
+++ b/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1
@@ -1,6 +1,6 @@
@{
RootModule = 'PSOPNSenseAPI.psm1'
- ModuleVersion = '2025.04.14.2253'
+ ModuleVersion = '2025.04.14.2306'
GUID = '1f0e4b77-cc7c-4a1e-b45a-d7c51a3c562e'
Author = 'PSOPNSenseAPI Contributors'
CompanyName = 'PSOPNSenseAPI'
diff --git a/output/PSOPNSenseAPI/lib/PSOPNSenseAPI.dll b/output/PSOPNSenseAPI/lib/PSOPNSenseAPI.dll
index 46c59f8..d4f7805 100644
Binary files a/output/PSOPNSenseAPI/lib/PSOPNSenseAPI.dll and b/output/PSOPNSenseAPI/lib/PSOPNSenseAPI.dll differ
diff --git a/src/PSOPNSenseAPI/PSOPNSenseAPI.csproj b/src/PSOPNSenseAPI/PSOPNSenseAPI.csproj
index 51e99b2..7133ec5 100644
--- a/src/PSOPNSenseAPI/PSOPNSenseAPI.csproj
+++ b/src/PSOPNSenseAPI/PSOPNSenseAPI.csproj
@@ -4,7 +4,7 @@
netstandard2.0;net472
PSOPNSenseAPI
PSOPNSenseAPI
- 2025.04.14.2253
+ 2025.04.14.2306
PSOPNSenseAPI Contributors
PSOPNSenseAPI
PowerShell module for interacting with the OPNSense API to configure firewalls
diff --git a/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1 b/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1
index f82a537..d2a03a7 100644
--- a/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1
+++ b/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1
@@ -1,9 +1,9 @@
@{
# Script module or binary module file associated with this manifest.
- RootModule = 'PSOPNSenseAPI.dll'
+ RootModule = 'PSOPNSenseAPI.psm1'
# Version number of this module.
- ModuleVersion = '0.5.0'
+ ModuleVersion = '2025.04.14.2306'
# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')
@@ -45,7 +45,7 @@
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
- RequiredAssemblies = @('System.Net.Http', 'Newtonsoft.Json', 'System.Net.IPNetwork')
+ # RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
diff --git a/src/PSOPNSenseAPI/Services/PortForwardingService.cs.bak b/src/PSOPNSenseAPI/Services/PortForwardingService.cs.bak
deleted file mode 100644
index bb2b7d5..0000000
--- a/src/PSOPNSenseAPI/Services/PortForwardingService.cs.bak
+++ /dev/null
@@ -1,202 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using PSOPNSenseAPI.Models;
-
-namespace PSOPNSenseAPI.Services
-{
- ///
- /// Service for managing port forwarding rules in OPNSense
- ///
- public class PortForwardingService : ServiceBase
- {
- ///
- /// Initializes a new instance of the class
- ///
- /// The API client to use for requests
- public PortForwardingService(ApiClient apiClient) : base(apiClient)
- {
- }
-
- ///
- /// Gets all port forwarding rules
- ///
- /// A list of port forwarding rules
- public async Task> GetPortForwardingRulesAsync()
- {
- var response = await ApiClient.GetAsync("/firewall/nat/getRule");
- var responseContent = await response.Content.ReadAsStringAsync();
- var jsonResponse = JObject.Parse(responseContent);
-
- if (jsonResponse["status"]?.ToString() != "ok")
- {
- throw new Exception($"Failed to get port forwarding rules: {jsonResponse["status_msg"]}");
- }
-
- var rules = new List();
- var rulesData = jsonResponse["rows"];
-
- foreach (var rule in rulesData)
- {
- var portForwardingRule = new PortForwardingRule
- {
- Uuid = rule["uuid"]?.ToString(),
- Enabled = rule["enabled"]?.ToString() == "1",
- Description = rule["descr"]?.ToString(),
- Interface = rule["interface"]?.ToString(),
- Protocol = rule["protocol"]?.ToString(),
- Source = rule["source"]?.ToString(),
- SourcePort = rule["source_port"]?.ToString(),
- Destination = rule["destination"]?.ToString(),
- DestinationPort = rule["destination_port"]?.ToString(),
- TargetIP = rule["target"]?.ToString(),
- TargetPort = rule["target_port"]?.ToString(),
- NatReflection = rule["natreflection"]?.ToString(),
- FilterRuleAssociation = rule["associated-rule-id"]?.ToString() != "none",
- Log = rule["log"]?.ToString() == "1"
- };
-
- rules.Add(portForwardingRule);
- }
-
- return rules;
- }
-
- ///
- /// Gets a port forwarding rule by UUID
- ///
- /// The UUID of the rule to get
- /// The port forwarding rule
- public async Task GetPortForwardingRuleAsync(string uuid)
- {
- var rules = await GetPortForwardingRulesAsync();
- return rules.Find(r => r.Uuid == uuid);
- }
-
- ///
- /// Creates a new port forwarding rule
- ///
- /// The rule to create
- /// The UUID of the created rule
- public async Task CreatePortForwardingRuleAsync(PortForwardingRule rule)
- {
- var ruleData = new
- {
- rule = new
- {
- enabled = rule.Enabled ? "1" : "0",
- descr = rule.Description,
- interface = rule.Interface,
- protocol = rule.Protocol,
- source = rule.Source,
- source_port = rule.SourcePort,
- destination = rule.Destination,
- destination_port = rule.DestinationPort,
- target = rule.TargetIP,
- target_port = rule.TargetPort,
- natreflection = rule.NatReflection,
- associated_rule_id = rule.FilterRuleAssociation ? "pass" : "none",
- log = rule.Log ? "1" : "0"
- }
- };
-
- var response = await ApiClient.PostAsync("/firewall/nat/addRule", ruleData);
- var responseContent = await response.Content.ReadAsStringAsync();
- var jsonResponse = JObject.Parse(responseContent);
-
- if (jsonResponse["status"]?.ToString() != "ok")
- {
- throw new Exception($"Failed to create port forwarding rule: {jsonResponse["status_msg"]}");
- }
-
- // Apply changes
- await ApplyChangesAsync();
-
- return jsonResponse["uuid"]?.ToString();
- }
-
- ///
- /// Updates an existing port forwarding rule
- ///
- /// The rule to update
- /// True if successful
- public async Task UpdatePortForwardingRuleAsync(PortForwardingRule rule)
- {
- if (string.IsNullOrEmpty(rule.Uuid))
- {
- throw new ArgumentException("Rule UUID cannot be null or empty", nameof(rule));
- }
-
- var ruleData = new
- {
- rule = new
- {
- enabled = rule.Enabled ? "1" : "0",
- descr = rule.Description,
- interface = rule.Interface,
- protocol = rule.Protocol,
- source = rule.Source,
- source_port = rule.SourcePort,
- destination = rule.Destination,
- destination_port = rule.DestinationPort,
- target = rule.TargetIP,
- target_port = rule.TargetPort,
- natreflection = rule.NatReflection,
- associated_rule_id = rule.FilterRuleAssociation ? "pass" : "none",
- log = rule.Log ? "1" : "0"
- }
- };
-
- var response = await ApiClient.PostAsync($"/firewall/nat/setRule/{rule.Uuid}", ruleData);
- var responseContent = await response.Content.ReadAsStringAsync();
- var jsonResponse = JObject.Parse(responseContent);
-
- if (jsonResponse["status"]?.ToString() != "ok")
- {
- throw new Exception($"Failed to update port forwarding rule: {jsonResponse["status_msg"]}");
- }
-
- // Apply changes
- await ApplyChangesAsync();
-
- return true;
- }
-
- ///
- /// Deletes a port forwarding rule
- ///
- /// The UUID of the rule to delete
- /// True if successful
- public async Task DeletePortForwardingRuleAsync(string uuid)
- {
- var response = await ApiClient.PostAsync($"/firewall/nat/delRule/{uuid}", null);
- var responseContent = await response.Content.ReadAsStringAsync();
- var jsonResponse = JObject.Parse(responseContent);
-
- if (jsonResponse["status"]?.ToString() != "ok")
- {
- throw new Exception($"Failed to delete port forwarding rule: {jsonResponse["status_msg"]}");
- }
-
- // Apply changes
- await ApplyChangesAsync();
-
- return true;
- }
-
- ///
- /// Applies the changes to the firewall
- ///
- /// True if successful
- private async Task ApplyChangesAsync()
- {
- var response = await ApiClient.PostAsync("/firewall/nat/apply", null);
- var responseContent = await response.Content.ReadAsStringAsync();
- var jsonResponse = JObject.Parse(responseContent);
-
- return jsonResponse["status"]?.ToString() == "ok";
- }
- }
-}
diff --git a/temp_interface_service.cs b/temp_interface_service.cs
deleted file mode 100644
index b448b00..0000000
--- a/temp_interface_service.cs
+++ /dev/null
@@ -1,289 +0,0 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-using PSOPNSenseAPI.Logging;
-using PSOPNSenseAPI.Models;
-
-namespace PSOPNSenseAPI.Services
-{
- public class InterfaceService
- {
- private readonly OPNSenseApiClient _apiClient;
- private readonly ILogger _logger;
-
- public InterfaceService(OPNSenseApiClient apiClient, ILogger logger)
- {
- _apiClient = apiClient;
- _logger = logger;
- }
-
- public async Task GetInterfacesAsync()
- {
- _logger.Information("Getting interfaces");
-
- var endpoint = "interfaces/overview/searchInterfaces";
- return await _apiClient.GetAsync(endpoint);
- }
-
- public async Task GetInterfaceDetailAsync(string interfaceName)
- {
- _logger.Information($"Getting interface {interfaceName}");
-
- var endpoint = $"interfaces/overview/getInterface/{interfaceName}";
- return await _apiClient.GetAsync(endpoint);
- }
-
- public async Task GetInterfaceStatisticsAsync()
- {
- _logger.Information("Getting interface statistics");
-
- var endpoint = "diagnostics/interface/getInterfaceStatistics";
- return await _apiClient.GetAsync(endpoint);
- }
-
- public async Task UpdateInterfaceAsync(string interfaceName, InterfaceConfig interfaceConfig)
- {
- _logger.Information($"Updating interface {interfaceName}");
-
- var endpoint = $"interfaces/overview/setInterface/{interfaceName}";
- var data = new { interface = interfaceConfig };
- return await _apiClient.PostAsync(endpoint, data);
- }
-
- public async Task RestartInterfaceAsync(string interfaceName)
- {
- _logger.Information($"Restarting interface {interfaceName}");
-
- var endpoint = $"interfaces/overview/reconfigure/{interfaceName}";
- return await _apiClient.PostAsync(endpoint);
- }
-
- public async Task GetVLANsAsync()
- {
- _logger.Information("Getting VLANs");
-
- var endpoint = "interfaces/vlan/searchItem";
- return await _apiClient.GetAsync(endpoint);
- }
-
- public async Task GetVLANAsync(string uuid)
- {
- _logger.Information($"Getting VLAN with UUID {uuid}");
-
- var endpoint = $"interfaces/vlan/getItem/{uuid}";
- return await _apiClient.GetAsync(endpoint);
- }
-
- public async Task CreateVLANAsync(VLANConfig vlan)
- {
- _logger.Information("Creating VLAN");
-
- var endpoint = "interfaces/vlan/addItem";
- var data = new { vlan = vlan };
- return await _apiClient.PostAsync(endpoint, data);
- }
-
- public async Task UpdateVLANAsync(string uuid, VLANConfig vlan)
- {
- _logger.Information($"Updating VLAN with UUID {uuid}");
-
- var endpoint = $"interfaces/vlan/setItem/{uuid}";
- var data = new { vlan = vlan };
- return await _apiClient.PostAsync(endpoint, data);
- }
-
- public async Task DeleteVLANAsync(string uuid)
- {
- _logger.Information($"Deleting VLAN with UUID {uuid}");
-
- var endpoint = $"interfaces/vlan/delItem/{uuid}";
- return await _apiClient.PostAsync(endpoint);
- }
- }
-
- public class InterfaceListResponse
- {
- [JsonProperty("rows")]
- public List Interfaces { get; set; }
- }
-
- public class InterfaceInfo
- {
- [JsonProperty("name")]
- public string Name { get; set; }
-
- [JsonProperty("description")]
- public string Description { get; set; }
-
- [JsonProperty("ipaddr")]
- public string IpAddress { get; set; }
-
- [JsonProperty("subnet")]
- public string SubnetMask { get; set; }
-
- [JsonProperty("gateway")]
- public string Gateway { get; set; }
-
- [JsonProperty("status")]
- public string Status { get; set; }
- }
-
- public class InterfaceDetailResponse
- {
- [JsonProperty("interface")]
- public InterfaceDetail Interface { get; set; }
- }
-
- public class InterfaceDetail
- {
- [JsonProperty("name")]
- public string Name { get; set; }
-
- [JsonProperty("description")]
- public string Description { get; set; }
-
- [JsonProperty("ipaddr")]
- public string IpAddress { get; set; }
-
- [JsonProperty("subnet")]
- public string SubnetMask { get; set; }
-
- [JsonProperty("gateway")]
- public string Gateway { get; set; }
-
- [JsonProperty("enable")]
- public string Enabled { get; set; }
- }
-
- public class InterfaceConfig
- {
- [JsonProperty("description")]
- public string Description { get; set; }
-
- [JsonProperty("ipaddr")]
- public string IpAddress { get; set; }
-
- [JsonProperty("subnet")]
- public string SubnetMask { get; set; }
-
- [JsonProperty("gateway")]
- public string Gateway { get; set; }
-
- [JsonProperty("enable")]
- public string Enabled { get; set; }
- }
-
- public class InterfaceUpdateResponse
- {
- [JsonProperty("result")]
- public string Result { get; set; }
- }
-
- public class InterfaceRestartResponse
- {
- [JsonProperty("status")]
- public string Status { get; set; }
- }
-
- public class InterfaceStatisticsResponse
- {
- [JsonProperty("statistics")]
- public Dictionary Statistics { get; set; }
- }
-
- public class InterfaceStatistics
- {
- [JsonProperty("name")]
- public string Name { get; set; }
-
- [JsonProperty("inpkts")]
- public string InPackets { get; set; }
-
- [JsonProperty("outpkts")]
- public string OutPackets { get; set; }
-
- [JsonProperty("inbytes")]
- public string InBytes { get; set; }
-
- [JsonProperty("outbytes")]
- public string OutBytes { get; set; }
- }
-
- public class VLANListResponse
- {
- [JsonProperty("rows")]
- public List Rows { get; set; }
- }
-
- public class VLAN
- {
- [JsonProperty("uuid")]
- public string Uuid { get; set; }
-
- [JsonProperty("if")]
- public string Interface { get; set; }
-
- [JsonProperty("tag")]
- public string Tag { get; set; }
-
- [JsonProperty("pcp")]
- public string Priority { get; set; }
-
- [JsonProperty("descr")]
- public string Description { get; set; }
- }
-
- public class VLANResponse
- {
- [JsonProperty("vlan")]
- public VLANDetail Vlan { get; set; }
- }
-
- public class VLANDetail
- {
- [JsonProperty("if")]
- public string Interface { get; set; }
-
- [JsonProperty("tag")]
- public string Tag { get; set; }
-
- [JsonProperty("pcp")]
- public string Priority { get; set; }
-
- [JsonProperty("descr")]
- public string Description { get; set; }
- }
-
- public class VLANConfig
- {
- [JsonProperty("if")]
- public string Interface { get; set; }
-
- [JsonProperty("tag")]
- public string Tag { get; set; }
-
- [JsonProperty("pcp")]
- public string Priority { get; set; }
-
- [JsonProperty("descr")]
- public string Description { get; set; }
- }
-
- public class VLANCreateResponse
- {
- [JsonProperty("uuid")]
- public string Uuid { get; set; }
- }
-
- public class VLANUpdateResponse
- {
- [JsonProperty("result")]
- public string Result { get; set; }
- }
-
- public class VLANDeleteResponse
- {
- [JsonProperty("result")]
- public string Result { get; set; }
- }
-}