Modules/Interfaces/GraphQLInterface.vb
2022-10-24 13:16:38 +02:00

246 lines
8.7 KiB
VB.net

Imports System.IO
Imports System.Net
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports DigitalData.Modules.Logging
Imports Newtonsoft.Json
Public Class GraphQLInterface
Private _logConfig As LogConfig
Private _logger As Logger
Private _baseUrl As String
Private _userEmail As String
Private _userPassword As String
Private _certificate As X509Certificate2
Private _cookieJar As CookieContainer
Private _Encoding As New UTF8Encoding
Private Const MAX_COOKIE_SIZE As Integer = 32768
Private Const MAX_COOKIE_COUNT As Integer = 300
Private Const MAX_COOKIE_COUNT_PER_DOMAIN As Integer = 20
Public Property Proxy As WebProxy
Public Property Credentials As NetworkCredential
Public Sub New(LogConfig As LogConfig, BaseUrl As String, Email As String, Password As String, CertificateFingerprint As String)
Try
_logConfig = LogConfig
_logger = LogConfig.GetLogger()
_baseUrl = BaseUrl
_userEmail = Email
_userPassword = Password
Dim oStoreNames As New List(Of StoreName) From {StoreName.Root, StoreName.My}
Dim oStoreLocations As New List(Of StoreLocation) From {StoreLocation.CurrentUser, StoreLocation.LocalMachine}
Dim oCertificate As X509Certificate2 = Nothing
For Each oStoreLocation In oStoreLocations
_logger.Debug("Checking Stores in Location [{0}]", oStoreLocation.ToString)
For Each oStoreName In oStoreNames
oCertificate = FindCertificateByFingerprint(oStoreLocation, oStoreName, CertificateFingerprint, False)
If oCertificate IsNot Nothing Then
_logger.Info("Certificate found in Store [{0}]/[{1}]!", oStoreName.ToString, oStoreLocation.ToString)
Exit For
End If
Next
Next
If oCertificate Is Nothing Then
_logger.Warn("Certificate could not be found! Exiting.")
Exit Sub
End If
_certificate = oCertificate
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
Private Function FindCertificateByFingerprint(pLocation As StoreLocation, pStoreName As StoreName, pFingerprint As String, pValidOnly As Boolean) As X509Certificate2
Try
Dim oStore As New X509Store(pStoreName, pLocation)
Dim oLocation As String = pLocation.ToString
_logger.Info("Opening Store [{0}]/[{1}]..", oLocation, oStore.Name)
oStore.Open(OpenFlags.ReadOnly)
_logger.Info("Available Certificates in Store [{0}]/[{1}]: [{2}]", oLocation, oStore.Name, oStore.Certificates.Count)
For Each oCert In oStore.Certificates
_logger.Debug("FriendlyName: {0}", oCert.FriendlyName)
_logger.Debug("IssuerName: {0}", oCert.IssuerName.Name)
_logger.Debug("SubjectName: {0}", oCert.SubjectName.Name)
_logger.Debug("Fingerprint: {0}", oCert.Thumbprint)
Next
_logger.Debug("Looking for Certificate with Fingerprint [{0}]", pFingerprint)
Dim oFoundCerts = oStore.Certificates.Find(X509FindType.FindByThumbprint, pFingerprint, pValidOnly)
_logger.Debug("Closing store..")
oStore.Close()
If oFoundCerts.Count = 0 Then
_logger.Debug("Certificate with Fingerprint [{0}] not found in Store [{1}]/[{2}]", pFingerprint, oLocation, oStore.Name)
Return Nothing
End If
Return oFoundCerts.Item(0)
Catch ex As Exception
_logger.Warn("Unexpected error while searching for certificate with Fingerprint [{0}].", pFingerprint)
_logger.Error(ex)
Return Nothing
End Try
End Function
Public Sub SaveCookies(Cookie As Cookie)
GetCookies().Add(Cookie)
End Sub
Public Function Login() As HttpWebResponse
Try
Dim oLoginData As New LoginData() With {.email = _userEmail, .token = _userPassword}
Dim oBytes As Byte() = ToBytes(JsonConvert.SerializeObject(oLoginData))
Dim oRequest As HttpWebRequest = GetRequest("/login", oBytes)
Using oStream = oRequest.GetRequestStream()
oStream.Write(oBytes, 0, oBytes.Length)
End Using
Return oRequest.GetResponse()
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Public Function Logout() As HttpWebResponse
Try
Dim oLogoutData As New LogoutData() With {.email = _userEmail}
Dim oBytes As Byte() = ToBytes(JsonConvert.SerializeObject(oLogoutData))
Dim oRequest As HttpWebRequest = GetRequest("/logout", oBytes)
Using stream = oRequest.GetRequestStream()
stream.Write(oBytes, 0, oBytes.Length)
End Using
Return oRequest.GetResponse()
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Public Function GetData(Query As String, OperationName As String) As HttpWebResponse
Try
Dim oQueryData As New QueryData() With {
.operationName = OperationName,
.query = Query,
.variables = New Object
}
Dim oJson = JsonConvert.SerializeObject(oQueryData)
Dim oBytes = ToBytes(oJson)
Dim oRequest = GetRequest("/graphql", oBytes)
Using stream = oRequest.GetRequestStream()
stream.Write(oBytes, 0, oBytes.Length)
End Using
Return oRequest.GetResponse()
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Public Function ReadJSONPathFragmented(pObject As Linq.JObject, pJsonPath As String)
Dim oSplitPath As List(Of String) = pJsonPath.Split(".").ToList()
Dim oCurrentPath As String = String.Empty
For Each oPart In oSplitPath
If oCurrentPath = String.Empty Then
oCurrentPath = oPart
Else
oCurrentPath &= "." & oPart
End If
_logger.Debug("Selecting Path Fragment [{0}]", oCurrentPath)
Try
pObject.SelectToken(oCurrentPath, errorWhenNoMatch:=True)
Catch ex As Exception
_logger.Warn("Path Fragment [{0}] did not return a valid token", oCurrentPath)
Return False
End Try
Next
Return True
End Function
Private Function GetRequest(Url As String, PostData As Byte()) As HttpWebRequest
Try
' Set supported TLS versions for WebRequest
' Source: https://stackoverflow.com/questions/10822509/the-request-was-aborted-could-not-create-ssl-tls-secure-channel
'SetSecurityOptions()
'SetSecurityOptionsInsecure()
'SetSecurityOptionsModern()
Dim oRequest As HttpWebRequest = WebRequest.Create($"{_baseUrl}{Url}")
oRequest.Method = "POST"
oRequest.ContentType = "application/json"
oRequest.ContentLength = PostData.Length
oRequest.ClientCertificates.Add(_certificate)
oRequest.CookieContainer = GetCookies()
oRequest.Proxy = Nothing
If Proxy Is Nothing Then
oRequest.Proxy = Nothing
Else
oRequest.Proxy = Proxy
oRequest.Credentials = Credentials
End If
Return oRequest
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Private Sub SetSecurityOptions()
ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls Or
SecurityProtocolType.Tls11 Or
SecurityProtocolType.Tls12
End Sub
Private Sub SetSecurityOptionsInsecure()
ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls Or
SecurityProtocolType.Tls11 Or
SecurityProtocolType.Tls12 Or
SecurityProtocolType.Ssl3
End Sub
Private Sub SetSecurityOptionsModern()
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
End Sub
Private Function GetCookies() As CookieContainer
If _cookieJar Is Nothing Then
_cookieJar = New CookieContainer(MAX_COOKIE_COUNT, MAX_COOKIE_COUNT_PER_DOMAIN, MAX_COOKIE_SIZE)
End If
Return _cookieJar
End Function
Private Function ToBytes(Str As String) As Byte()
Return _Encoding.GetBytes(Str)
End Function
End Class