Important note about SSL VPN compatibility for 20.0 MR1 with EoL SFOS versions and UTM9 OS. Learn more in the release notes.

This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Sophos XG API Powershell Module - sophosxg-api

Hi All,

As a professional development and learning exercise I wrote this powershell module.

I do not claim it to be free from errors/bugs and is for learning and testing. Use at your own risk. 

I thought it may be of some value to others out there. 

https://github.com/strooth/SophosXg-Api 



This thread was automatically locked due to age.
Parents
  • Could you give us / me some insights, what you API actually can perform? 

    You are settings some values to configure a XG, correct? 

     

     

    If you want to get some "clicks clicks clicks", build Certbot + DNAT + Lets Encrypt Upload + Replacement Script.

    Seems like you know, what you are doing, and this is highly asked by some people.

    The script should perform something like: 

    Enable a specific DNAT Rule every 2 Month. (Port80 to the powershell server?).

    Start Certbot to generate new LE certificates.

    Disable DNAT Rule.

    Upload new LE Certificate to XG

    Replace in Webadmin the LE Certificate

    Check in Firewall Rule for WAF Rules, replace if yes, replace the Certificate

    (Clean up old LE certificate). 

     

    As a little help: https://community.sophos.com/products/xg-firewall/f/sophos-xg-firewall-general-discussion/102208/upload-certificate-using-api

     

    __________________________________________________________________________________________________________________

Reply
  • Could you give us / me some insights, what you API actually can perform? 

    You are settings some values to configure a XG, correct? 

     

     

    If you want to get some "clicks clicks clicks", build Certbot + DNAT + Lets Encrypt Upload + Replacement Script.

    Seems like you know, what you are doing, and this is highly asked by some people.

    The script should perform something like: 

    Enable a specific DNAT Rule every 2 Month. (Port80 to the powershell server?).

    Start Certbot to generate new LE certificates.

    Disable DNAT Rule.

    Upload new LE Certificate to XG

    Replace in Webadmin the LE Certificate

    Check in Firewall Rule for WAF Rules, replace if yes, replace the Certificate

    (Clean up old LE certificate). 

     

    As a little help: https://community.sophos.com/products/xg-firewall/f/sophos-xg-firewall-general-discussion/102208/upload-certificate-using-api

     

    __________________________________________________________________________________________________________________

Children
  • To see what the certificate looks like (or any request) first do a get request of the object and you will then have an object (or many) with which you can update/modify/template. The documentation from sophos is also included in a folder there for reference with all data constraints. The database is Postgres so look there if you need to know more info about scalar etc (just a string).

    The basic request can be achieved by just running New-XgApi and populating with the correct information. Following then you can run Invoke-XgApi which will spit out what the certificates look like (you could do a get filter to select just 1 if you have multiple)

    To actually have a working script that is unattended you will need to use the class object instead however.

    $myvar = new-xgapi -out_object and then populate the values in your script or splat the object with New-XgApi -object $object which is filled with the information from certbot etc

    You can see examples of both in on in the example files

    I would love to help, I don't think I will have much spare time unfortunately. I'll see if I can help at some point :)

  • Wrote this last weekend after reading your suggestion and looking at what others had written just haven't got around to including it into the module.
     
    You should be able to figure out the acme renewal etc yourself and use this to do the upload.
     
    function Invoke-MultipartFormRequest
    {
      [CmdletBinding()]
      param (
        [Parameter(ParameterSetName = '0', Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [string]$FilePath,
        [Parameter(ParameterSetName = '0', Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [string]$uri,
        [Parameter(ParameterSetName = '0', Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [string]$request
      )
      begin
      {
        #add classes
        Add-Type -AssemblyName System.Web
        Add-Type -AssemblyName System.Net.Http
        #create http client
        $httpClientHandler = New-Object System.Net.Http.HttpClientHandler
        $httpClient = New-Object System.Net.Http.Httpclient $httpClientHandler
        #Create File upload
        $ContentType = "application/octet-stream"
        $file = Get-Item -Path $FilePath
        $contentDispositionHeaderValue = New-Object System.Net.Http.Headers.ContentDispositionHeaderValue "form-data"
        $contentDispositionHeaderValue.Name = "`"$((Get-Item $File).Basename)`""
        $contentDispositionHeaderValue.FileName = "`"$((Get-Item $File).Name)`""
        $HeaderContentType = New-Object System.Net.Http.Headers.MediaTypeHeaderValue $ContentType
        $packageFileStream = New-Object System.IO.FileStream @($File, [System.IO.FileMode]::Open)
        $streamContent = New-Object System.Net.Http.StreamContent $packageFileStream
        $streamContent.Headers.ContentDisposition = $contentDispositionHeaderValue
        $streamContent.Headers.ContentType = $HeaderContentType
        #create req part
        $messageDispositionValue = New-Object System.Net.Http.Headers.ContentDispositionHeaderValue "form-data"
        $messageDispositionValue.Name = "reqxml"
        $messageContent = New-Object System.Net.Http.StringContent $request
        $messageContent.Headers.ContentDisposition = $messageDispositionValue
        $ContentType = "application/xml; charset=utf-8"
        $messageContent.Headers.ContentType = $ContentType
        #create content to send
        $content = New-Object System.Net.Http.MultipartFormDataContent
        $content.Add($messageContent)
        $content.Add($streamContent)
        if ($uri.Substring($uri.Length - 1) -ne '?') { $uri = $uri + '?' }
      }
      process
      {
        try
        {
          $response = $httpClient.PostAsync($uri, $content).Result
        }
        catch
        {
          $PSCmdlet.ThrowTerminatingError($error[0])
        }
        finally
        {
          $content.Dispose()
          $messageContent.Dispose()
          $streamContent.Dispose()
          $packageFileStream.Close()
          $packageFileStream.Dispose()
          $httpClient.CancelPendingRequests()
          $httpClient.Dispose()
          $httpClientHandler.Dispose()
        }
      }
      end
      {
        return $response
      }
    }
  • and if you can upgrade to powershell 7 its very easy 

     

    $request = '<Request><login><username>username</username><name>username</name><password passwordform="`"encrypt`"">password</password></login><Set operation="`"add`""><Certificate><Name>cert</Name><Action>UploadCertificate</Action><CertificateFormat>cer</CertificateFormat><CertificateFile>cert.cer</CertificateFile></Certificate></Set></Request>'
    $file = "C:\certs\cert.cer"
    $Form = @{
        reqxml  = $request
        $((Get-Item $File).Basename) = Get-Item -Path $file
    }
    $Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form