Sophos Firewall: PowerShell Script Library for migrating Sophos UTM to Sophos Firewall

Disclaimer: This information is provided as-is for the benefit of the Community. Please contact Sophos Professional Services if you require assistance with your specific environment.


Overview

This Recommended read describes ways to migrate Sophos UTM Configurations parts to Sophos Firewall, with UTM API and Import/Export Features.

This will also include Powershell Scripts to migrate some Features and options. 

Migration Desk

This is free to all Partners (and subsequently customers) that will assist in planning, executing, and verifying migrations of your existing firewall or Sophos UTM to Sophos Firewall migrations.

The following scripts follow an easy approach: This will download the configuration via JSON UTM API and convert this content to an XML File. The XML File is usable in SFOS for more information about the approach.

Sophos UTM offers a full API and a "Swagger" tool for the entire configuration.

Accessing API

You can access the API of Sophos UTM by using https://IP:4444/api 

The Swagger UI offers you the Schema UTM uses for every feature.

For example, Network Host Objects

It’ll show you the CURL request and Token you need to do to GET the data. You’ll also see the format in this code. 

We can now use the data we get via API and convert it to XML Data. We need to map the matching points of UTM to SFOS.


In the example below, We map the data of the UTM "name" to the SFOS name, and we'll map the IP address to the IP address. Then, add the rest of the XML code, which is static. The approach of this migration is always the same: fetch the data, convert it to XML, and save it. 

Kindly replace the IP and the Authorization Token in the Script and run it via Powershell. 

Convert Host Objects to XML

#Code to accept untrusted UTM connections. Not needed, if you use a trusted CA for the UTM webadmin. 

add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
            return true;
        }
 }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" -Position 0



# Define the URL for the API // Replace the IP with your UTM IP. 
$url = "https://172.25.105.16:4444/api/objects/network/host/"

# Define the headers for the request // Replace the Authorization Code with your UTM Code. See Swagger. 
$headers = @{
    Accept = "application/json"
    Authorization = "Basic YWRtaW46U29waG9zLjE="
}

# Send a GET request to the API and store the result in a variable
$jsonResult = Invoke-RestMethod -Uri $url -Headers $headers -Method Get

# Convert the JSON data to XML
$xmlResult = [xml]@"
<?xml version="1.0" encoding="UTF-8"?>
<Configuration APIVersion="1905.1" IPS_CAT_VER="1">
$(
    foreach ($item in $jsonResult) {
        "  <IPHost>"
        "    <Name>$($item.name)</Name>"
        "    <IPFamily>IPv4</IPFamily>"
        "    <HostType>IP</HostType>"
        "    <IPAddress>$($item.address)</IPAddress>"
        "  </IPHost>"
    }
)
</Configuration>
"@

# Save the XML data to a file in the same directory as the script
$filePath = Join-Path -Path (Split-Path -Path $MyInvocation.MyCommand.Path -Parent) -ChildPath "Entities.xml"
$xmlResult.Save($filePath)
=

Convert Network Objects to XML 

add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
            return true;
        }
 }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" -Position 0
# Define the URL for the API // Replace the IP with your UTM IP. 
$url = "https://172.25.105.16:4444/api/objects/network/network/"

# Define the headers for the request // Replace the Authorization Code with your UTM Code. See Swagger. 
$headers = @{
    Accept = "application/json"
    Authorization = "Basic YWRtaW46U29waG9zLjE="
}

# Send a GET request to the API and store the result in a variable
$jsonResult = Invoke-RestMethod -Uri $url -Headers $headers -Method Get

# Define the subnet mask mapping
$subnetMasks = @("0.0.0.0","128.0.0.0","192.0.0.0","224.0.0.0","240.0.0.0","248.0.0.0","252.0.0.0","254.0.0.0",
                 "255.0.0.0","255.128.0.0","255.192.0.0","255.224.0.0","255.240.0.0","255.248.0.0","255.252.0.0","255.254.0.0",
                 "255.255.0.0","255.255.128.0","255.255.192.0","255.255.224.0","255.255.240.0","255.255.248.0","255.255.252.0","255.255.254.0",
                 "255.255.255.0","255.255.255.128","255.255.255.192","255.255.255.224","255.255.255.240","255.255.255.248","255.255.255.252","255.255.255.254","255.255.255.255")

# Convert the JSON data to XML
$xmlResult = [xml]@"
<?xml version="1.0" encoding="UTF-8"?>
<Configuration APIVersion="1905.1" IPS_CAT_VER="1">
$(
    foreach ($item in $jsonResult) {
        "  <IPHost>"
        "    <Name>$($item.name)</Name>"
        "    <IPFamily>IPv4</IPFamily>"
        "    <HostType>Network</HostType>"
        "    <IPAddress>$($item.address)</IPAddress>"
		"	<Subnet>$($subnetMasks[$item.netmask])</Subnet>"
        "  </IPHost>"
 }
)
</Configuration>
"@

# Save the XML data to a file in the same directory as the script
$filePath = Join-Path -Path (Split-Path -Path $MyInvocation.MyCommand.Path -Parent) -ChildPath "Entities.xml"
$xmlResult.Save($filePath)

Convert REDs from UTM to SFOS

Use this code with Caution. RED can only be deployed with one Firewall (UTM or SFOS). If you register the RED from UTM to SFOS, iRED will begin to restart. 
This code is very static and won’t migrate complex RED deployments like UMTS, Transparent / Split, or other scenarios. It won’t migrate DHCP Servers but will keep the IP Addresses of the REDs. 

add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
            return true;
        }
 }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" -Position 0
# Define the URL for the API // Replace the IP with your UTM IP. 
$url = "https://172.25.105.16:4444/api/objects/itfhw/red_server/"
$url2 = "https://172.25.105.16:4444/api/objects/interface/ethernet/"
$url3 = "https://172.25.105.16:4444/api/objects/itfparams/primary/"

# Define the headers for the request // Replace the Authorization Code with your UTM Code. See Swagger. 
$headers = @{
    Accept = "application/json"
    Authorization = "Basic YWRtaW46U29waG9zLjE="
}

# Send a GET request to the API and store the result in a variable
$jsonResult = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
$jsonEthernet = Invoke-RestMethod -Uri $url2 -Headers $headers -Method Get
$jsonparams = Invoke-RestMethod -Uri $url3 -Headers $headers -Method Get

#SubnetMasks
$subnetMasks = @("0.0.0.0","128.0.0.0","192.0.0.0","224.0.0.0","240.0.0.0","248.0.0.0","252.0.0.0","254.0.0.0",
                 "255.0.0.0","255.128.0.0","255.192.0.0","255.224.0.0","255.240.0.0","255.248.0.0","255.252.0.0","255.254.0.0",
                 "255.255.0.0","255.255.128.0","255.255.192.0","255.255.224.0","255.255.240.0","255.255.248.0","255.255.252.0","255.255.254.0",
                 "255.255.255.0","255.255.255.128","255.255.255.192","255.255.255.224","255.255.255.240","255.255.255.248","255.255.255.252","255.255.255.254","255.255.255.255")

# Convert the JSON data to XML
$xmlResult = [xml]@"
<?xml version="1.0" encoding="UTF-8"?>
<Configuration APIVersion="1905.1" IPS_CAT_VER="1">
$(
    foreach ($item in $jsonResult) {
	$itfmatch =  $jsonEthernet | Where-Object {$_.itfhw -eq $item._ref}
	$ip = $jsonparams | Where-Object {$_._ref -eq $itfmatch.primary_address}
	"		<REDDevice transactionid="""">"
	"		<BranchName>$($item.name)</BranchName>"
	"		<Device>$($item.type)</Device>"
	"		<REDDeviceID>$($item.red_id)</REDDeviceID>"
	"		<TunnelID>Automatic</TunnelID>"
	"		<REDMTU>1500</REDMTU>"
	"		<Description>$($item.comment)</Description>"
	"		<NetworkSetting>"
	"			<Zone>LAN</Zone>"
    "           <DhcpStatus>Disable</DhcpStatus>"
	"			<TunnelCompression>Disable</TunnelCompression>"
	"			<OperationMode>Standard</OperationMode>"
	"			<IPAddress>$($ip.address)</IPAddress>"
	"			<NetMask>$($subnetMasks[$ip.netmask])</NetMask>"
	"			<MACFilter>"
	"		<FilterType>None</FilterType>"
	"			</MACFilter>"
	"		</NetworkSetting>"
	"		<Authorized>1</Authorized>"
	"		<UnlockCode>$($item.unlock_code)</UnlockCode>"
	"		<UTMHostName>$($item.hub_hostname)</UTMHostName>"
	"		<SecondUTMHostName>$($item.hub2_hostname)</SecondUTMHostName>"
	"		<Use2ndIPHostNameFor>Failover</Use2ndIPHostNameFor>"
	"		<DeploymentMode>AutoDeployment</DeploymentMode>"
	"		<UplinkSettings>"
	"			<Uplink>"
	"			<Connection>DHCP</Connection>"
	"			</Uplink>"
	"			<UMTS3GFailover>Disable</UMTS3GFailover>"
	"		</UplinkSettings>"
	"		</REDDevice>"
 }
)
</Configuration>
"@

# Save the XML data to a file in the same directory as the script
$filePath = Join-Path -Path (Split-Path -Path $MyInvocation.MyCommand.Path -Parent) -ChildPath "Entities.xml"
$xmlResult.Save($filePath)

Important Note: The code will generate XML Files for SFOSv19.5. If you want to use the XML in an older version of SFOS, adjust the following line: 
<Configuration APIVersion="1905.1" IPS_CAT_VER="1">     

Feel free to contribute more code for migration scenarios. We’ll provide more code in the future. 




Revamped RR Corrected Grammar & Font Size Added Horizontal Lines
[edited by: Erick Jan at 11:56 AM (GMT -7) on 28 Sep 2023]
Parents
  • I am about to build the IPsec Site to Site Tunnel migration part, but bumping into the problem of "local / remote Subnet" section. Therefore i am about to release the Powershell script without the migration of Local / remote Subnet or i can migrate only "the names" and the admin has to migrate the objects before. 

    As UTM and SFOS uses only the names of the objects (Network 1), i can migrate the names, but the names have to exists before the migration. 

    __________________________________________________________________________________________________________________

Reply
  • I am about to build the IPsec Site to Site Tunnel migration part, but bumping into the problem of "local / remote Subnet" section. Therefore i am about to release the Powershell script without the migration of Local / remote Subnet or i can migrate only "the names" and the admin has to migrate the objects before. 

    As UTM and SFOS uses only the names of the objects (Network 1), i can migrate the names, but the names have to exists before the migration. 

    __________________________________________________________________________________________________________________

Children
No Data