Update configuration management cmdlets

- Added Get-OPNSenseConfig cmdlet that retrieves the OPNSense configuration as an XML document
- Updated Restore-OPNSenseConfig to accept an XML document from the pipeline or as a parameter
- Changed Export-OPNSenseConfig and Import-OPNSenseConfig to use System.IO.FileInfo for the Path parameter
- Removed Backup-OPNSenseConfig cmdlet (use Get-OPNSenseConfig instead)
- Updated documentation and examples
This commit is contained in:
GraceSolutions
2025-04-15 08:53:09 -04:00
parent c423cca25a
commit 68e6819131
16 changed files with 654 additions and 108 deletions
+9 -1
View File
@@ -5,12 +5,20 @@ All notable changes to the PSOPNSenseAPI module will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2025.04.15.0739] - 2025-04-15
## [2025.04.15.1143] - 2025-04-15
### Added
- Added `Get-OPNSenseConfig` cmdlet that retrieves the OPNSense configuration as an XML document
### Changed
- Renamed `Upgrade-OPNSenseFirmware` to `Start-OPNSenseFirmwareUpgrade` to resolve cmdlet name conflict
- Updated `Restore-OPNSenseConfig` to accept an XML document from the pipeline or as a parameter
- Changed `Export-OPNSenseConfig` and `Import-OPNSenseConfig` to use System.IO.FileInfo for the Path parameter
- Added unit tests for firmware management cmdlets
### Removed
- Removed `Backup-OPNSenseConfig` cmdlet (use `Get-OPNSenseConfig` instead)
## [0.6.0] - 2025-04-14
### Added
+5 -3
View File
@@ -141,9 +141,11 @@ Start-OPNSenseFirmwareUpgrade -Wait -Timeout 1200
# Reboot firewall
Restart-OPNSenseFirewall -Wait -Timeout 300
# Backup and restore configuration
Backup-OPNSenseConfig -Filename "pre-upgrade-backup"
Export-OPNSenseConfig -Path "C:\Backups\opnsense-config.xml"
# Configuration management
Get-OPNSenseConfig | Restore-OPNSenseConfig -Force # Get and restore configuration in one line
$config = Get-OPNSenseConfig # Get configuration as XML document
Export-OPNSenseConfig -Path (New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml")
Import-OPNSenseConfig -Path (New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml") -Force
```
## Documentation
+76
View File
@@ -0,0 +1,76 @@
# Export-OPNSenseConfig
## SYNOPSIS
Exports the OPNSense firewall configuration.
## SYNTAX
```
Export-OPNSenseConfig -Path <FileInfo> [-Force]
```
## DESCRIPTION
The Export-OPNSenseConfig cmdlet exports the OPNSense firewall configuration to a file.
## EXAMPLES
### Example 1: Export the configuration to a file
```powershell
$path = New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml"
Export-OPNSenseConfig -Path $path
```
This example exports the OPNSense firewall configuration to a file.
## PARAMETERS
### -Path
The path to save the configuration file. Must be a FileInfo object with an .xml extension.
```yaml
Type: FileInfo
Parameter Sets: (All)
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Force
Overwrites the file if it exists.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### None
## NOTES
This cmdlet requires a connection to an OPNSense firewall. Use Connect-OPNSense to establish a connection.
If the directory specified in the Path parameter does not exist, it will be created.
## RELATED LINKS
[Get-OPNSenseConfig](Get-OPNSenseConfig.md)
[Import-OPNSenseConfig](Import-OPNSenseConfig.md)
[Restore-OPNSenseConfig](Restore-OPNSenseConfig.md)
+52
View File
@@ -0,0 +1,52 @@
# Get-OPNSenseConfig
## SYNOPSIS
Gets the OPNSense firewall configuration as an XML document.
## SYNTAX
```
Get-OPNSenseConfig
```
## DESCRIPTION
The Get-OPNSenseConfig cmdlet retrieves the OPNSense firewall configuration and returns it as an XML document.
## EXAMPLES
### Example 1: Get the configuration as an XML document
```powershell
$config = Get-OPNSenseConfig
```
This example retrieves the OPNSense firewall configuration as an XML document.
### Example 2: Get the configuration and pipe it to Restore-OPNSenseConfig
```powershell
Get-OPNSenseConfig | Restore-OPNSenseConfig
```
This example retrieves the OPNSense firewall configuration and restores it.
## PARAMETERS
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Xml.XmlDocument
The OPNSense configuration as an XML document.
## NOTES
This cmdlet requires a connection to an OPNSense firewall. Use Connect-OPNSense to establish a connection.
## RELATED LINKS
[Restore-OPNSenseConfig](Restore-OPNSenseConfig.md)
[Export-OPNSenseConfig](Export-OPNSenseConfig.md)
[Import-OPNSenseConfig](Import-OPNSenseConfig.md)
+106
View File
@@ -0,0 +1,106 @@
# Import-OPNSenseConfig
## SYNOPSIS
Imports an OPNSense firewall configuration.
## SYNTAX
```
Import-OPNSenseConfig -Path <FileInfo> [-Force] [-WhatIf] [-Confirm]
```
## DESCRIPTION
The Import-OPNSenseConfig cmdlet imports an OPNSense firewall configuration from a file.
## EXAMPLES
### Example 1: Import a configuration from a file
```powershell
$path = New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml"
Import-OPNSenseConfig -Path $path
```
This example imports an OPNSense firewall configuration from a file.
## PARAMETERS
### -Path
The path to the configuration file. Must be a FileInfo object with an .xml extension.
```yaml
Type: FileInfo
Parameter Sets: (All)
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Force
Suppresses the confirmation prompt.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -WhatIf
Shows what would happen if the cmdlet runs. The cmdlet is not run.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases: wi
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Confirm
Prompts you for confirmation before running the cmdlet.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases: cf
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### None
## NOTES
This cmdlet requires a connection to an OPNSense firewall. Use Connect-OPNSense to establish a connection.
The firewall will restart after the configuration is imported.
## RELATED LINKS
[Get-OPNSenseConfig](Get-OPNSenseConfig.md)
[Export-OPNSenseConfig](Export-OPNSenseConfig.md)
[Restore-OPNSenseConfig](Restore-OPNSenseConfig.md)
+142
View File
@@ -0,0 +1,142 @@
# Restore-OPNSenseConfig
## SYNOPSIS
Restores an OPNSense firewall configuration.
## SYNTAX
### Filename
```
Restore-OPNSenseConfig -Filename <String> [-Force] [-WhatIf] [-Confirm]
```
### XmlDocument
```
Restore-OPNSenseConfig -XmlDocument <XmlDocument> [-Force] [-WhatIf] [-Confirm]
```
## DESCRIPTION
The Restore-OPNSenseConfig cmdlet restores an OPNSense firewall configuration from a backup or an XML document.
## EXAMPLES
### Example 1: Restore a configuration backup
```powershell
Restore-OPNSenseConfig -Filename "config-backup-20250414-1234.xml"
```
This example restores an OPNSense firewall configuration from a backup file.
### Example 2: Restore a configuration from an XML document
```powershell
$config = Get-OPNSenseConfig
Restore-OPNSenseConfig -XmlDocument $config
```
This example restores an OPNSense firewall configuration from an XML document.
### Example 3: Restore a configuration from the pipeline
```powershell
Get-OPNSenseConfig | Restore-OPNSenseConfig
```
This example restores an OPNSense firewall configuration from the pipeline.
## PARAMETERS
### -Filename
The filename of the backup to restore.
```yaml
Type: String
Parameter Sets: Filename
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -XmlDocument
The XML document containing the configuration to restore.
```yaml
Type: XmlDocument
Parameter Sets: XmlDocument
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: True (ByValue)
Accept wildcard characters: False
```
### -Force
Suppresses the confirmation prompt.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -WhatIf
Shows what would happen if the cmdlet runs. The cmdlet is not run.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases: wi
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Confirm
Prompts you for confirmation before running the cmdlet.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases: cf
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### System.Xml.XmlDocument
An XML document containing the OPNSense configuration.
## OUTPUTS
### None
## NOTES
This cmdlet requires a connection to an OPNSense firewall. Use Connect-OPNSense to establish a connection.
The firewall will restart after the configuration is restored.
## RELATED LINKS
[Get-OPNSenseConfig](Get-OPNSenseConfig.md)
[Export-OPNSenseConfig](Export-OPNSenseConfig.md)
[Import-OPNSenseConfig](Import-OPNSenseConfig.md)
+15 -8
View File
@@ -8,22 +8,29 @@ Connect-OPNSense -Server "https://firewall.example.com" -ApiKey "your_api_key" -
$backups = Get-OPNSenseConfigBackup
$backups | Format-Table -Property Filename, Description, FileSize, Date, Version
# Create a new configuration backup
$backupFilename = Backup-OPNSenseConfig -Filename "pre-upgrade-backup"
Write-Output "Created backup: $backupFilename"
# Get the current configuration as an XML document
$config = Get-OPNSenseConfig
Write-Output "Retrieved configuration with root element: $($config.DocumentElement.Name)"
# Export the configuration to a file
$exportPath = "C:\Backups\opnsense-config.xml"
$exportPath = New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml"
Export-OPNSenseConfig -Path $exportPath -Force
Write-Output "Exported configuration to: $exportPath"
Write-Output "Exported configuration to: $($exportPath.FullName)"
# Import a configuration from a file
# Note: This will restart the firewall
# Import-OPNSenseConfig -Path $exportPath -Confirm
# Import-OPNSenseConfig -Path $exportPath -Force
# Restore a configuration backup
# Restore a configuration backup by filename
# Note: This will restart the firewall
# Restore-OPNSenseConfig -Filename $backupFilename -Confirm
# Restore-OPNSenseConfig -Filename "config-backup-20250415-1234.xml" -Force
# Restore a configuration from an XML document
# Note: This will restart the firewall
# Restore-OPNSenseConfig -XmlDocument $config -Force
# Pipeline example: Get and restore configuration in one line
# Get-OPNSenseConfig | Restore-OPNSenseConfig -Force
# Disconnect from the firewall
Disconnect-OPNSense
+108 -14
View File
@@ -1,19 +1,70 @@
@{
# Script module or binary module file associated with this manifest.
RootModule = 'PSOPNSenseAPI.psm1'
ModuleVersion = '2025.04.15.0739'
GUID = '1f0e4b77-cc7c-4a1e-b45a-d7c51a3c562e'
Author = 'PSOPNSenseAPI Contributors'
CompanyName = 'PSOPNSenseAPI'
Copyright = 'Copyright (c) 2025 PSOPNSenseAPI Contributors'
Description = 'PowerShell module for interacting with the OPNSense API to configure firewalls'
PowerShellVersion = '5.1'
# Version number of this module.
ModuleVersion = '2025.04.15.1143'
# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')
#DotNetFrameworkVersion = '4.7.2'
CLRVersion = '4.0.0'
# ID used to uniquely identify this module
GUID = '9a3b4c55-5f9a-4b8c-87d9-9a7a5cdd5c9f'
# Author of this module
Author = 'PSOPNSenseAPI Contributors'
# Company or vendor of this module
CompanyName = 'PSOPNSenseAPI'
# Copyright statement for this module
Copyright = '(c) 2025 PSOPNSenseAPI Contributors. All rights reserved.'
# Description of the functionality provided by this module
Description = 'PowerShell module for interacting with the OPNSense API to configure firewalls'
# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'
# Name of the PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
DotNetFrameworkVersion = '4.7.2'
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
ClrVersion = '4.0'
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
NestedModules = @('lib\PSOPNSenseAPI.dll')
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @()
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @(
'Apply-OPNSenseFirewallChanges',
'Backup-OPNSenseConfig',
'Connect-OPNSense',
'Connect-OPNSenseTailscale',
'ConvertTo-OPNSenseNetworkNotation',
@@ -29,6 +80,7 @@
'Enable-OPNSenseTailscale',
'Export-OPNSenseConfig',
'Get-OPNSenseAlias',
'Get-OPNSenseConfig',
'Get-OPNSenseConfigBackup',
'Get-OPNSenseConnection',
'Get-OPNSenseCronJob',
@@ -104,16 +156,58 @@
'Update-OPNSenseFirmware',
'Start-OPNSenseFirmwareUpgrade'
)
# Variables to export from this module
VariablesToExport = @()
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
RequiredAssemblies = @('lib\System.Net.IPNetwork.dll', 'lib\Newtonsoft.Json.dll')
NestedModules = @('lib\PSOPNSenseAPI.dll')
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('PowerShell', 'OPNSense', 'Firewall', 'API')
# A URL to the license for this module.
LicenseUri = 'https://github.com/freedbygrace/PSOPNSenseAPI/blob/main/LICENSE'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/freedbygrace/PSOPNSenseAPI'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
ReleaseNotes = 'https://github.com/freedbygrace/PSOPNSenseAPI/blob/main/CHANGELOG.md'
}
}
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfoURI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
+13 -2
View File
@@ -1,2 +1,13 @@
# This file is intentionally empty.
# The module uses NestedModules in the PSD1 file to load the assemblies.
# Load the main assembly directly
$mainDllPath = Join-Path $PSScriptRoot "lib\PSOPNSenseAPI.dll"
Write-Verbose "Loading assembly from $mainDllPath"
try {
Add-Type -Path $mainDllPath
Write-Verbose "Successfully loaded assembly from $mainDllPath"
} catch {
$errorMessage = $_.Exception.Message
Write-Error "Failed to load assembly from $($mainDllPath): $($errorMessage)"
throw
}
Binary file not shown.
@@ -1,53 +0,0 @@
using System;
using System.Management.Automation;
using System.Threading.Tasks;
using PSOPNSenseAPI.Services;
namespace PSOPNSenseAPI.Cmdlets
{
/// <summary>
/// <para type="synopsis">Creates a backup of the OPNSense firewall configuration.</para>
/// <para type="description">The Backup-OPNSenseConfig cmdlet creates a backup of the OPNSense firewall configuration.</para>
/// <example>
/// <para>Example 1: Create a backup</para>
/// <code>Backup-OPNSenseConfig</code>
/// <para>This example creates a backup of the OPNSense firewall configuration with an automatically generated filename.</para>
/// </example>
/// <example>
/// <para>Example 2: Create a backup with a specific filename</para>
/// <code>Backup-OPNSenseConfig -Filename "pre-upgrade-backup"</code>
/// <para>This example creates a backup of the OPNSense firewall configuration with a specific filename.</para>
/// </example>
/// </summary>
[Cmdlet(VerbsData.Backup, "OPNSenseConfig")]
[OutputType(typeof(string))]
public class BackupOPNSenseConfigCmdlet : OPNSenseBaseCmdlet
{
/// <summary>
/// <para type="description">The filename for the backup.</para>
/// </summary>
[Parameter(Mandatory = false, Position = 0)]
public string Filename { get; set; }
/// <summary>
/// Processes the cmdlet
/// </summary>
protected override void ProcessRecord()
{
try
{
var configService = new ConfigService(ApiClient, Logger);
var task = Task.Run(async () => await configService.CreateConfigBackupAsync(Filename));
var result = task.GetAwaiter().GetResult();
WriteVerbose($"Created configuration backup: {result.Filename}");
WriteObject(result.Filename);
}
catch (Exception ex)
{
HandleException(ex);
}
}
}
}
@@ -23,8 +23,8 @@ namespace PSOPNSenseAPI.Cmdlets
/// <para type="description">The path to save the configuration file.</para>
/// </summary>
[Parameter(Mandatory = true, Position = 0)]
[ValidateNotNullOrEmpty]
public string Path { get; set; }
[ValidateNotNull]
public FileInfo Path { get; set; }
/// <summary>
/// <para type="description">Overwrites the file if it exists.</para>
@@ -39,14 +39,16 @@ namespace PSOPNSenseAPI.Cmdlets
{
try
{
string fullPath = Path.FullName;
// Check if the file exists
if (File.Exists(Path) && !Force.IsPresent)
if (File.Exists(fullPath) && !Force.IsPresent)
{
WriteError(new ErrorRecord(
new IOException($"The file '{Path}' already exists. Use -Force to overwrite."),
new IOException($"The file '{fullPath}' already exists. Use -Force to overwrite."),
"FileExists",
ErrorCategory.ResourceExists,
Path));
fullPath));
return;
}
@@ -56,16 +58,16 @@ namespace PSOPNSenseAPI.Cmdlets
var configContent = task.GetAwaiter().GetResult();
// Create the directory if it doesn't exist
var directory = System.IO.Path.GetDirectoryName(Path);
var directory = System.IO.Path.GetDirectoryName(fullPath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
// Write the configuration to the file
File.WriteAllBytes(Path, configContent);
File.WriteAllBytes(fullPath, configContent);
WriteVerbose($"Exported configuration to {Path}");
WriteVerbose($"Exported configuration to {fullPath}");
}
catch (Exception ex)
{
@@ -0,0 +1,56 @@
using System;
using System.IO;
using System.Management.Automation;
using System.Threading.Tasks;
using System.Xml;
using PSOPNSenseAPI.Services;
namespace PSOPNSenseAPI.Cmdlets
{
/// <summary>
/// <para type="synopsis">Gets the OPNSense firewall configuration as an XML document.</para>
/// <para type="description">The Get-OPNSenseConfig cmdlet retrieves the OPNSense firewall configuration and returns it as an XML document.</para>
/// <example>
/// <para>Example 1: Get the configuration as an XML document</para>
/// <code>$config = Get-OPNSenseConfig</code>
/// <para>This example retrieves the OPNSense firewall configuration as an XML document.</para>
/// </example>
/// <example>
/// <para>Example 2: Get the configuration and pipe it to Restore-OPNSenseConfig</para>
/// <code>Get-OPNSenseConfig | Restore-OPNSenseConfig</code>
/// <para>This example retrieves the OPNSense firewall configuration and restores it.</para>
/// </example>
/// </summary>
[Cmdlet(VerbsCommon.Get, "OPNSenseConfig")]
[OutputType(typeof(XmlDocument))]
public class GetOPNSenseConfigCmdlet : OPNSenseBaseCmdlet
{
/// <summary>
/// Processes the cmdlet
/// </summary>
protected override void ProcessRecord()
{
try
{
var configService = new ConfigService(ApiClient, Logger);
var task = Task.Run(async () => await configService.ExportConfigAsync());
var configContent = task.GetAwaiter().GetResult();
// Convert the byte array to an XML document
var xmlDoc = new XmlDocument();
using (var memoryStream = new MemoryStream(configContent))
{
xmlDoc.Load(memoryStream);
}
WriteVerbose("Retrieved OPNSense configuration as XML document");
WriteObject(xmlDoc);
}
catch (Exception ex)
{
HandleException(ex);
}
}
}
}
@@ -23,8 +23,8 @@ namespace PSOPNSenseAPI.Cmdlets
/// <para type="description">The path to the configuration file.</para>
/// </summary>
[Parameter(Mandatory = true, Position = 0)]
[ValidateNotNullOrEmpty]
public string Path { get; set; }
[ValidateNotNull]
public FileInfo Path { get; set; }
/// <summary>
/// <para type="description">Suppresses the confirmation prompt.</para>
@@ -39,18 +39,20 @@ namespace PSOPNSenseAPI.Cmdlets
{
try
{
string fullPath = Path.FullName;
// Check if the file exists
if (!File.Exists(Path))
if (!File.Exists(fullPath))
{
WriteError(new ErrorRecord(
new FileNotFoundException($"The file '{Path}' does not exist."),
new FileNotFoundException($"The file '{fullPath}' does not exist."),
"FileNotFound",
ErrorCategory.ObjectNotFound,
Path));
fullPath));
return;
}
if (!Force.IsPresent && !ShouldProcess(Path, "Import configuration"))
if (!Force.IsPresent && !ShouldProcess(fullPath, "Import configuration"))
{
return;
}
@@ -58,12 +60,12 @@ namespace PSOPNSenseAPI.Cmdlets
var configService = new ConfigService(ApiClient, Logger);
// Read the configuration file
var configContent = File.ReadAllBytes(Path);
var configContent = File.ReadAllBytes(fullPath);
var task = Task.Run(async () => await configService.ImportConfigAsync(configContent));
var result = task.GetAwaiter().GetResult();
WriteVerbose($"Imported configuration from {Path}: {result.Status}");
WriteVerbose($"Imported configuration from {fullPath}: {result.Status}");
WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online.");
}
catch (Exception ex)
@@ -1,18 +1,30 @@
using System;
using System.IO;
using System.Management.Automation;
using System.Threading.Tasks;
using System.Xml;
using PSOPNSenseAPI.Services;
namespace PSOPNSenseAPI.Cmdlets
{
/// <summary>
/// <para type="synopsis">Restores an OPNSense firewall configuration from a backup.</para>
/// <para type="description">The Restore-OPNSenseConfig cmdlet restores an OPNSense firewall configuration from a backup.</para>
/// <para type="synopsis">Restores an OPNSense firewall configuration.</para>
/// <para type="description">The Restore-OPNSenseConfig cmdlet restores an OPNSense firewall configuration from a backup or an XML document.</para>
/// <example>
/// <para>Example 1: Restore a configuration backup</para>
/// <code>Restore-OPNSenseConfig -Filename "config-backup-20250414-1234.xml"</code>
/// <para>This example restores an OPNSense firewall configuration from a backup file.</para>
/// </example>
/// <example>
/// <para>Example 2: Restore a configuration from an XML document</para>
/// <code>$config = Get-OPNSenseConfig; Restore-OPNSenseConfig -XmlDocument $config</code>
/// <para>This example restores an OPNSense firewall configuration from an XML document.</para>
/// </example>
/// <example>
/// <para>Example 3: Restore a configuration from the pipeline</para>
/// <code>Get-OPNSenseConfig | Restore-OPNSenseConfig</code>
/// <para>This example restores an OPNSense firewall configuration from the pipeline.</para>
/// </example>
/// </summary>
[Cmdlet(VerbsData.Restore, "OPNSenseConfig", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)]
[OutputType(typeof(void))]
@@ -21,10 +33,17 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary>
/// <para type="description">The filename of the backup to restore.</para>
/// </summary>
[Parameter(Mandatory = true, Position = 0)]
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "Filename")]
[ValidateNotNullOrEmpty]
public string Filename { get; set; }
/// <summary>
/// <para type="description">The XML document containing the configuration to restore.</para>
/// </summary>
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "XmlDocument", ValueFromPipeline = true)]
[ValidateNotNull]
public XmlDocument XmlDocument { get; set; }
/// <summary>
/// <para type="description">Suppresses the confirmation prompt.</para>
/// </summary>
@@ -38,17 +57,39 @@ namespace PSOPNSenseAPI.Cmdlets
{
try
{
if (!Force.IsPresent && !ShouldProcess(Filename, "Restore configuration backup"))
var configService = new ConfigService(ApiClient, Logger);
string actionDescription = "Restore configuration";
string targetName = ParameterSetName == "Filename" ? Filename : "from XML document";
if (!Force.IsPresent && !ShouldProcess(targetName, actionDescription))
{
return;
}
var configService = new ConfigService(ApiClient, Logger);
if (ParameterSetName == "Filename")
{
// Restore from backup file
var task = Task.Run(async () => await configService.RestoreConfigBackupAsync(Filename));
var result = task.GetAwaiter().GetResult();
var task = Task.Run(async () => await configService.RestoreConfigBackupAsync(Filename));
var result = task.GetAwaiter().GetResult();
WriteVerbose($"Restored configuration from backup: {result.Status}");
}
else
{
// Restore from XML document
byte[] configContent;
using (var memoryStream = new MemoryStream())
{
XmlDocument.Save(memoryStream);
configContent = memoryStream.ToArray();
}
var task = Task.Run(async () => await configService.ImportConfigAsync(configContent));
var result = task.GetAwaiter().GetResult();
WriteVerbose($"Restored configuration from XML document: {result.Status}");
}
WriteVerbose($"Restored configuration backup: {result.Status}");
WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online.");
}
catch (Exception ex)
+3 -3
View File
@@ -3,7 +3,7 @@
RootModule = 'PSOPNSenseAPI.psm1'
# Version number of this module.
ModuleVersion = '2025.04.15.0739'
ModuleVersion = '2025.04.15.1143'
# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')
@@ -57,7 +57,7 @@
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
NestedModules = @('lib\PSOPNSenseAPI.dll')
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @()
@@ -65,7 +65,6 @@
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @(
'Apply-OPNSenseFirewallChanges',
'Backup-OPNSenseConfig',
'Connect-OPNSense',
'Connect-OPNSenseTailscale',
'ConvertTo-OPNSenseNetworkNotation',
@@ -81,6 +80,7 @@
'Enable-OPNSenseTailscale',
'Export-OPNSenseConfig',
'Get-OPNSenseAlias',
'Get-OPNSenseConfig',
'Get-OPNSenseConfigBackup',
'Get-OPNSenseConnection',
'Get-OPNSenseCronJob',