Imports System.Web
Imports System.Net
Imports System.Text
Imports System.ComponentModel
Imports Newtonsoft.Json
Imports MyApp.Common
Imports MyApp.Common.JSON
Public Class SonicWallAPI
Inherits APIBase
Public Enum SonicOSVersion
<Description("https://{0}:{1}/api/sonicos/")> Gen6
<Description("https://{0}:{1}/api/sonicos/")> Gen7
End Enum
Private Const SonicOSFTPURI As String = "ftp://{0}:{1}@{2}/"
Private LoggedIn As Boolean = False
Private APIHeaders As WebHeaderCollection
Private APIEndpoint As String = String.Empty
Private JSONResponse As String = String.Empty
Protected Property AuthorizationString As String
Private ReadOnly APIVersion As SonicOSVersion
Private ReadOnly FTPServer As FileTransferServerSettings = ApplicationSettings.CertifyToolsConfiguration.CertifyTools.FTPServer
Private ReadOnly PFXCredentials As NetworkCredential
Private ReadOnly BaseURL As String
Public Sub New(ByVal SonicOSHost As String, ByVal SonicOSPort As Integer, ByVal SonicOSCredentials As NetworkCredential,
Optional ByVal Version As SonicOSVersion = SonicOSVersion.Gen6,
Optional ByVal PFXCredential As NetworkCredential = Nothing,
Optional ByVal FTPSettings As FileTransferServerSettings = Nothing)
MyBase.New
If Version <> SonicOSVersion.Gen6 AndAlso Version <> SonicOSVersion.Gen7 Then
Throw New ArgumentException("Invalid API version selected", NameOf(Version))
End If
Me.LoggedIn = False
Me.APIVersion = Version
Me.BaseURL = Me.APIVersion.GetDescription
Me.API_URL = String.Format(BaseURL, SonicOSHost, SonicOSPort.ToString)
Me.APIHeaders = New WebHeaderCollection
Me.FTPServer = FTPSettings
If PFXCredential IsNot Nothing Then
Me.PFXCredentials = New NetworkCredential(PFXCredential.Username, PFXCredential.Password)
End If
Me.AuthorizationString = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(SonicOSCredentials.Username + ":" + SonicOSCredentials.Password))
Me.APIHeaders.Add("Authorization", Me.AuthorizationString)
End Sub
''' <summary>
''' Log in and create a new session on the SonicWALL appliance
''' </summary>
Public Sub Login()
Me.APIEndpoint = "auth"
Me.JSONResponse = SubmitAPIRequest(Me.API_URL, WebMethod.HTTPPOST, Me.APIEndpoint, AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim Authorization As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
If Authorization.Status.Success Then
Me.LoggedIn = True
Else
Me.LoggedIn = False
Throw New Exception("Login to SonicWALL appliance failed")
End If
Else
Me.LoggedIn = False
Throw New Exception(Me.JSONResponse)
End If
End Sub
''' <summary>
''' Log out of the current session on the SonicWALL appliance
''' </summary>
Public Sub Logout()
Me.APIEndpoint = "auth"
Me.JSONResponse = SubmitAPIRequest(Me.API_URL, WebMethod.HTTPDELETE, Me.APIEndpoint, AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim Authorization As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
If Authorization.Status.Success Then
Me.LoggedIn = False
End If
End If
End Sub
''' <summary>
''' Import a new SSL certificate from a PFX file provided by the Certificate Authority
''' </summary>
''' <param name="PFXFile">The PKCS12 file provided by the Certificate Authority containing the SSL certificate to be installed</param>
''' <returns></returns>
Public Function ImportCertificate(ByVal PFXFile As IO.FileInfo) As Boolean
If Me.LoggedIn Then
Dim FriendlyName As String = $"SSL Cert Issued {PFXFile.LastWriteTimeUtc.ToString("yyyy-MM-dd")}"
If Me.APIVersion = SonicOSVersion.Gen6 Then
Me.APIEndpoint = "certificates/import/cert-key-pair/name/{0}/password/{1}"
Else
Me.APIEndpoint = "import/certificates/cert-key-pair/name/{0}/password/{1}"
End If
If Me.FTPServer IsNot Nothing AndAlso Me.FTPServer.FTPServerHost IsNot Nothing AndAlso Not String.IsNullOrEmpty(Me.FTPServer.FTPServerHost) Then
Dim FTPServerIP As IPAddress = Nothing
IPAddress.TryParse(Me.FTPServer.FTPServerHost, FTPServerIP)
If FTPServerIP Is Nothing Then
IPAddress.TryParse(Dns.GetHostEntry(FTPServer.FTPServerHost).AddressList(0).ToString, FTPServerIP)
End If
If FTPServerIP IsNot Nothing Then
Dim FTPURL As String = String.Format(SonicOSFTPURI,
Me.FTPServer.FTPUser.Username,
Me.FTPServer.FTPUser.Password,
FTPServerIP.ToString) & PFXFile.Name
Me.APIEndpoint += "/ftp/{2}"
If Utility.FTP.FTPUpload(Me.FTPServer.FTPServerHost, Me.FTPServer.FTPUser, PFXFile) Then
Me.JSONResponse = SubmitAPIRequest(Me.API_URL,
WebMethod.HTTPPUT,
String.Format(Me.APIEndpoint,
HttpUtility.UrlEncode(FriendlyName),
HttpUtility.UrlEncode(Me.PFXCredentials.Password),
HttpUtility.UrlEncode(FTPURL)),
AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim APISuccess As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
If APISuccess.Status.Success Then
Return SetActiveSSLCertificate(FriendlyName)
End If
End If
End If
End If
Else
Dim MIMEType As String = "application/octet-stream"
If Me.APIVersion <> SonicOSVersion.Gen6 Then
MIMEType = Utility.MIME.GetMIMETypeFromFile(PFXFile)
End If
Me.JSONResponse = SubmitAPIRequest(Me.API_URL,
WebMethod.HTTPPUT,
String.Format(Me.APIEndpoint,
HttpUtility.UrlEncode(FriendlyName),
HttpUtility.UrlEncode(Me.PFXCredentials.Password)),
SubmitBody:=PFXFile,
BodyContentType:=MIMEType,
AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim APISuccess As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
If APISuccess.Status.Success Then
Return SetActiveSSLCertificate(FriendlyName)
End If
End If
End If
Else
Login()
Return ImportCertificate(PFXFile)
End If
Return False
End Function
''' <summary>
''' Specifies the active SSL certificate for the SonicWALL appliance to use
''' </summary>
''' <param name="FriendlyName">The Friendly Name of the certificate to set as active</param>
''' <returns></returns>
Private Function SetActiveSSLCertificate(ByVal FriendlyName As String) As Boolean
If Me.LoggedIn Then
Dim GlobalSettings As New SonicWALLAdministrationSettings With {
.AdminSettingsGroup = New SonicWALLAdministrationSettings.AdminSettings With {
.WebManagementConfiguration = New SonicWALLAdministrationSettings.AdminSettings.WebManagementSettings With {
.Certificate = New SonicWALLAdministrationSettings.AdminSettings.WebManagementSettings.SSLCertificate With {
.FriendlyName = FriendlyName
}
}
}
}
Me.APIEndpoint = "administration/global"
Me.JSONResponse = SubmitAPIRequest(Me.API_URL,
WebMethod.HTTPPUT,
Me.APIEndpoint,
SubmitBody:=JsonConvert.SerializeObject(GlobalSettings, ApplicationSettings.JSONSettings),
AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim APISuccess As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
If APISuccess.Status.Success Then
Return CommitPendingChanges()
Else
Return False
End If
Else
Return False
End If
Else
Login()
Return SetActiveSSLCertificate(FriendlyName)
End If
End Function
''' <summary>
''' Commits any pending changes to the SonicWALL appliance's configuration
''' </summary>
''' <param name="RestartDevice">Whether or not the SonicWALL appliance should be restarted after a successful commit</param>
''' <returns></returns>
Private Function CommitPendingChanges(Optional ByVal RestartDevice As Boolean = False) As Boolean
If Me.LoggedIn Then
Me.APIEndpoint = "config/pending"
Me.JSONResponse = SubmitAPIRequest(Me.API_URL, WebMethod.HTTPPOST, Me.APIEndpoint, AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim Authorization As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
Return Authorization.Status.Success
Else
Return False
End If
Else
Login()
Return CommitPendingChanges(RestartDevice)
End If
End Function
''' <summary>
''' Restart the SonicWALL appliance at the specified day/time
''' </summary>
''' <param name="RestartTime"></param>
''' <returns></returns>
Friend Function ScheduleRestart(ByVal RestartTime As Date) As Boolean
If Me.LoggedIn Then
Dim AT_TIME As String = RestartTime.ToString("yyyy:MM:dd:HH:mm:ss")
Me.APIEndpoint = $"restart/at/{AT_TIME}"
Me.JSONResponse = SubmitAPIRequest(Me.API_URL, WebMethod.HTTPPOST, Me.APIEndpoint, AdditionalHeaders:=Me.APIHeaders)
If Not Me.JSONResponse.StartsWith("NOT AUTHORIZED") Then
Dim Authorization As SonicWALLAPIResponse = JsonConvert.DeserializeObject(Of SonicWALLAPIResponse)(Me.JSONResponse)
Return Authorization.Status.Success
Else
Return False
End If
Else
Login()
Return ScheduleRestart(RestartTime)
End If
End Function
End Class