Skip to content

Commit

Permalink
Removed legacy authenthication from datapusher
Browse files Browse the repository at this point in the history
  • Loading branch information
gcsantos-gpa committed Oct 3, 2024
1 parent 42298bf commit dc172e7
Show file tree
Hide file tree
Showing 7 changed files with 13 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public Task SyncMeterConfigurationForInstance(string connectionId, int instanceI
DataPusherEngine engine = new DataPusherEngine(() => new AdoDataConnection("systemSettings"));
RemoteXDAInstance instance = new TableOperations<RemoteXDAInstance>(connection).QueryRecordWhere("ID = {0}", instanceId);
MetersToDataPush meter = new TableOperations<MetersToDataPush>(connection).QueryRecordWhere("ID = {0}", meterId);
DataPusherRequester requester = new DataPusherRequester(instance, connection);
DataPusherRequester requester = new DataPusherRequester(instance);
engine.SyncMeterConfigurationForInstance(connectionId, instance, meter, requester, cancellationToken);
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void PushDataToRemoteInstances(MeterDataSet meterDataSet)
post.MeterKey = metersToDataPush.RemoteXDAAssetKey;
Log.Info($"Sending data to instance: {instance.Name} for FileGroup: {meterDataSet.FileGroup.ID}...");
DataPusherEngine engine = new DataPusherEngine(meterDataSet.CreateDbConnection);
DataPusherRequester requester = new DataPusherRequester(instance, connection);
DataPusherRequester requester = new DataPusherRequester(instance);
engine.SendFiles(post, requester);


Expand Down
8 changes: 4 additions & 4 deletions Source/Libraries/openXDA.DataPusher/DataPusherEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ public void SyncInstanceConfiguration(string clientId, int instanceId, Cancellat
OnUpdateProgressForInstance(clientId, instance.Name, (int)(100 * (progressCount) / progressTotal));

// Do other operations needed
DataPusherRequester requester = new DataPusherRequester(instance, connection);
DataPusherRequester requester = new DataPusherRequester(instance);

List<Location> remoteLocations = new List<Location>();
IEnumerable<AssetTypes> localAssetTypes = new TableOperations<AssetTypes>(connection).QueryRecords();
Expand Down Expand Up @@ -969,7 +969,7 @@ private void AddAssetConnections(AssetConnection assetConnection, string connect
{
RemoteXDAInstance instance = new TableOperations<RemoteXDAInstance>(connection).QueryRecordWhere("ID = {0}", instanceId);
if (instance is null) throw new Exception($"No remote XDA instance found with this instance ID${instanceId}");
DataPusherRequester requester = new DataPusherRequester(instance, connection);
DataPusherRequester requester = new DataPusherRequester(instance);
return WebAPIHub.TestConnection(requester).GetAwaiter().GetResult();
}
}
Expand Down Expand Up @@ -1012,7 +1012,7 @@ public void SyncMeterFilesForInstance(string clientId, RemoteXDAInstance instanc
{
IEnumerable<FileGroup> localFileGroups;

DataPusherRequester requester = new DataPusherRequester(instance, connection);
DataPusherRequester requester = new DataPusherRequester(instance);
Settings settings = new Settings(GetConfigurator());

DateTime timeWindowStartDate = DateTime.UtcNow.AddHours(settings.DataPusherSettings.TimeWindow * -1);
Expand Down Expand Up @@ -1140,7 +1140,7 @@ public void SyncMeterFileForInstance(RemoteXDAInstance instance, MetersToDataPus
if (cancellationToken.IsCancellationRequested) return;
using (AdoDataConnection connection = ConnectionFactory())
{
DataPusherRequester requester = new DataPusherRequester(instance, connection);
DataPusherRequester requester = new DataPusherRequester(instance);

FileGroupLocalToRemote fileGroupLocalToRemote = new TableOperations<FileGroupLocalToRemote>(connection).QueryRecordWhere("LocalFileGroupID = {0} AND RemoteXDAInstanceID = {1}", fileGroupId, instance.ID);
FileGroup fileGroup = new TableOperations<FileGroup>(connection).QueryRecordWhere("ID = {0}", fileGroupId);
Expand Down
144 changes: 5 additions & 139 deletions Source/Libraries/openXDA.DataPusher/DataPusherRequester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,11 @@
//
//******************************************************************************************************

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using GSF;
using GSF.Configuration;
using GSF.Data;
using GSF.Data.Model;
using GSF.Net.Security;
using GSF.Security.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using openXDA.APIAuthentication;
Expand All @@ -43,61 +35,26 @@ namespace openXDA.DataPusher
{
public class DataPusherRequester
{
private UserAccount m_userAccount = null;

private string m_token = null;
private string m_key = null;

private string m_baseUrl = null;
private bool m_useApiAuth;

public static event EventHandler<EventArgs<string>> LogStatusMessageEvent;
public static event EventHandler<EventArgs<string>> LogExceptionMessageEvent;
private static readonly HttpClient staticClient = new HttpClient();
private static WebRequestHandler WebRequestHandler { get; }
private static HttpClient s_staticClient { get; }

#region [ Constructor ]

static DataPusherRequester()
{
WebRequestHandler = new WebRequestHandler();
WebRequestHandler.ServerCertificateValidationCallback = HandleCertificateValidation;
s_staticClient = new HttpClient(WebRequestHandler);
}

public DataPusherRequester(string instance, UserAccount userAccount)
{
m_baseUrl = instance.TrimEnd('/');
m_userAccount = userAccount;
m_useApiAuth = false;
}

public DataPusherRequester(string instance, string token, string key)
{
m_baseUrl = instance.TrimEnd('/');
m_token = token;
m_key = key;
m_useApiAuth = true;
}

public DataPusherRequester(int instanceID, AdoDataConnection connection) : this(new TableOperations<RemoteXDAInstance>(connection).QueryRecordWhere("ID = {0}", instanceID), connection) { }
public DataPusherRequester(int instanceID, AdoDataConnection connection) : this(new TableOperations<RemoteXDAInstance>(connection).QueryRecordWhere("ID = {0}", instanceID)) { }

public DataPusherRequester(RemoteXDAInstance instance, AdoDataConnection connection)
public DataPusherRequester(RemoteXDAInstance instance)
{
m_useApiAuth = instance.UseApiAuth;
if (instance.UseApiAuth)
{
m_baseUrl = instance.Address.TrimEnd('/');
m_token = instance.APIToken;
m_key = instance.RegistrationKey;
}
else
{
UserAccount userAccount = new TableOperations<UserAccount>(connection).QueryRecordWhere("ID = {0}", instance.UserAccountID);
m_baseUrl = instance.Address.TrimEnd('/');
m_userAccount = userAccount;
}
m_baseUrl = instance.Address.TrimEnd('/');
m_token = instance.APIToken;
m_key = instance.RegistrationKey;
}

#endregion
Expand All @@ -111,14 +68,6 @@ public async Task<HttpResponseMessage> SendRequestAsync(string path, HttpMethod
}

public async Task<HttpResponseMessage> SendRequestAsync(string path, HttpMethod method, HttpContent content = null, string mediaResponseType = "application/json")
{
if (m_useApiAuth)
return await SendAPIQueryAsync(path, method, content, mediaResponseType);
else
return await SendLegacyRequestAsync(path, method, content, mediaResponseType);
}

private async Task<HttpResponseMessage> SendAPIQueryAsync(string path, HttpMethod method, HttpContent content, string mediaResponseType)
{
APIQuery query = new APIQuery(m_key, m_token, m_baseUrl.Split(';'));

Expand All @@ -134,89 +83,6 @@ void ConfigureRequest(HttpRequestMessage request)
return await query.SendWebRequestAsync(ConfigureRequest, path);
}

private async Task<HttpResponseMessage> SendLegacyRequestAsync(string path, HttpMethod method, HttpContent content, string mediaResponseType)
{
string url = $"{m_baseUrl}/{path}";
string antiForgeryToken = await GenerateAntiForgeryTokenAsync(m_baseUrl, m_userAccount);

using (HttpRequestMessage request = new HttpRequestMessage(method, url))
{
ConfigureRequest(request, m_userAccount, mediaResponseType);
request.Headers.Add("X-GSF-Verify", antiForgeryToken);

if (!(content is null))
request.Content = content;

HttpResponseMessage response = await s_staticClient.SendAsync(request);
return response;
}
}

#endregion

#region [ Static ]
private static void OnLogStatusMessage(string message)
{
LogStatusMessageEvent?.Invoke(new object(), new EventArgs<string>(message));
}

private static void OnLogExceptionMessage(string message)
{
LogExceptionMessageEvent?.Invoke(new object(), new EventArgs<string>(message));
}

private static bool HandleCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
SimpleCertificateChecker simpleCertificateChecker = new SimpleCertificateChecker();

CategorizedSettingsElementCollection systemSettings = ConfigurationFile.Current.Settings["systemSettings"];
systemSettings.Add("CertFile", "", "Certificate for WebAPIHub used by PQMark/DataPusher.");
systemSettings.Add("ValidPolicyErrors", "None", "Expected policy errors during remote server certificate validation for PQMark/DataPusher (self-signed: RemoteCertificateNameMismatch, RemoteCertificateChainErrors).");
systemSettings.Add("ValidChainFlags", "NoError", "Expected chain flags set during remote server certificate validation for PQMark/DataPusher (self-signed: UntrustedRoot).");

try
{
simpleCertificateChecker.ValidPolicyErrors = (SslPolicyErrors)Enum.Parse(typeof(SslPolicyErrors), (systemSettings["ValidPolicyErrors"].Value != "All" ? systemSettings["ValidPolicyErrors"].Value : "7"));
simpleCertificateChecker.ValidChainFlags = (X509ChainStatusFlags)Enum.Parse(typeof(X509ChainStatusFlags), (systemSettings["ValidChainFlags"].Value != "All" ? systemSettings["ValidChainFlags"].Value : (~0).ToString()));
simpleCertificateChecker.TrustedCertificates.Add((!string.IsNullOrEmpty(systemSettings["CertFile"].Value) ? new X509Certificate2(systemSettings["CertFile"].Value) : certificate));
}
catch (Exception ex)
{
OnLogExceptionMessage(ex.ToString());
}

return simpleCertificateChecker.ValidateRemoteCertificate(sender, certificate, chain, sslPolicyErrors);
}

private static async Task<string> GenerateAntiForgeryTokenAsync(string instance, UserAccount userAccount)
{
string url = $"{instance}/api/PQMark/GenerateRequestVerficationToken";

using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url))
{
ConfigureRequest(request, userAccount, "application/json");

using (HttpResponseMessage response = await s_staticClient.SendAsync(request))
{
if (!response.IsSuccessStatusCode)
throw new InvalidOperationException($"Server returned status code {response.StatusCode}: {response.ReasonPhrase}");

return await response.Content.ReadAsStringAsync();
}
}
}

private static void ConfigureRequest(HttpRequestMessage request, UserAccount userAccount, string mediaResponseType)
{
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaResponseType));

Encoding utf8 = new UTF8Encoding(false);
string credential = $"{userAccount.AccountName}:{userAccount.Password}";
byte[] accountData = utf8.GetBytes(credential);
string encodedCredential = Convert.ToBase64String(accountData);
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", encodedCredential);
}

#endregion
}
}
Loading

0 comments on commit dc172e7

Please sign in to comment.