Prepare Data History Provider 2.7 integration update
- modularize Citrix and agent integrations and add remote desktop endpoints - extend ticket overview, ticket links, token validation, and staged relation handling - update configuration, licensing, project, signing, and publish artifacts
This commit is contained in:
95
F4SD-Cockpit-ServerCore/Modules/Agent/AgentApiHandler.cs
Normal file
95
F4SD-Cockpit-ServerCore/Modules/Agent/AgentApiHandler.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using C4IT.DataHistoryProvider.Base.Modules.Agent.DTOs;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Communication.Agent;
|
||||
using C4IT.HTTP;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
internal class AgentApiHandler : cHttpApiBase
|
||||
{
|
||||
private readonly Uri _baseUrl;
|
||||
private const string _agentLoginPath = "connect/token";
|
||||
private readonly cAgentApiConfiguration _agentConfig;
|
||||
|
||||
public AgentApiHandler(cAgentApiConfiguration agentConfig) : base("Agent ID tenant", $"{agentConfig.ApiUrl}/{agentConfig.LogonUrl}")
|
||||
{
|
||||
_agentConfig = agentConfig;
|
||||
_baseUrl = new Uri(_agentConfig.LogonUrl);
|
||||
AlwaysReturnContent = true;
|
||||
}
|
||||
|
||||
private protected override async Task<bool> privLogonAsync(cOAuthLogonInfo logonInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
var postData = new List<KeyValuePair<string, string>>()
|
||||
{
|
||||
new KeyValuePair<string, string>("grant_type", "client_credentials"),
|
||||
new KeyValuePair<string, string>("client_id", logonInfo.ClientID),
|
||||
new KeyValuePair<string, string>("client_secret", logonInfo.ClientSecret)
|
||||
};
|
||||
|
||||
var formData = new FormUrlEncodedContent(postData);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, new Uri(_baseUrl, _agentLoginPath)) { Content = formData };
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
var responseMessage = await response.Content.ReadAsStreamAsync();
|
||||
LogEntry($"F4SD Agent Logon failed. StatusCode: {response.StatusCode}");
|
||||
LogEntry($"F4SD Agent Logon failed. Response: {responseMessage}");
|
||||
return false;
|
||||
}
|
||||
|
||||
string responseContent = await response.Content.ReadAsStringAsync();
|
||||
var logonResult = JsonConvert.DeserializeObject<cAgentApiLogonInfo>(responseContent);
|
||||
|
||||
if (logonResult.TokenType.Equals("Bearer", StringComparison.OrdinalIgnoreCase) == false)
|
||||
{
|
||||
LogEntry("F4SD Agent Access token is not of type 'Bearer'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
cAgentApiLogonInfo.Instance = logonResult;
|
||||
AccessToken = logonResult.AccessToken;
|
||||
TokenExpiresIn = DateTime.UtcNow + TimeSpan.FromSeconds(logonResult.SecondsTillTokenExpires * RelogonFactor);
|
||||
IsOnline = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<T> Request<T>(string url, eHttpMethod httpMethod = eHttpMethod.get, object bodyData = null, CancellationToken token = default) where T : AgentApiResult
|
||||
{
|
||||
await LogonAsync(new cOAuthLogonInfo() { ClientID = _agentConfig.ClientId, ClientSecret = _agentConfig.ClientSecret, Tenant = "F4SD Agent" });
|
||||
Uri agentUrl = new Uri(_baseUrl, url);
|
||||
dynamic requestResult = await privRequestAsync(agentUrl.ToString(), httpMethod, bodyData, token: token);
|
||||
// todo handle not successfull status
|
||||
requestResult.ToObject<T>();
|
||||
string serialized = JsonConvert.SerializeObject(requestResult); // todo find better approach for casting the dynamic
|
||||
T deserialized = JsonConvert.DeserializeObject<T>(serialized);
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
internal async Task Request(string url, eHttpMethod httpMethod = eHttpMethod.get, object bodyData = null)
|
||||
=> await privRequestAsync(url, httpMethod, bodyData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
public class AgentRemoteClientInfo
|
||||
{
|
||||
[JsonProperty("orgCode")]
|
||||
public int OrganisationCode { get; set; }
|
||||
|
||||
[JsonProperty("deviceCode")]
|
||||
public int DeviceCode { get; set; }
|
||||
|
||||
[JsonProperty("accountCode")]
|
||||
public int AccountCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using C4IT.FASD.Communication.Agent;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
public class AgentRemoteConnectionInfo : AgentApiResult
|
||||
{
|
||||
[JsonProperty("connectionId")]
|
||||
public Guid ConnectionId { get; set; }
|
||||
|
||||
[JsonProperty("phoenixServiceUrl")]
|
||||
public Uri ServiceUrl { get; set; }
|
||||
|
||||
[JsonProperty("secret")]
|
||||
public string Secret { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using C4IT.DataHistoryProvider.Base.DataSources;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Communication.Agent;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
public class AgentRemoteDesktopManager : IRemoteDesktopManager<AgentRemoteConnectionInfo, AgentRemoteClientInfo, AgentRemoteConnectionStatusDto>
|
||||
{
|
||||
private readonly AgentApiHandler _agentApiHandler;
|
||||
|
||||
public AgentRemoteDesktopManager(cAgentApiConfiguration agentConfig)
|
||||
{
|
||||
_agentApiHandler = new AgentApiHandler(agentConfig);
|
||||
}
|
||||
|
||||
public async Task<AgentRemoteConnectionStatusDto> GetConnectionStatus(Guid connectionId)
|
||||
{
|
||||
return await _agentApiHandler.Request<AgentRemoteConnectionStatusDto>($"api/management/c4it/phoenix-connections/{connectionId}/status", HTTP.eHttpMethod.get);
|
||||
}
|
||||
|
||||
public async Task<AgentRemoteConnectionInfo> InitiateConnectionOfClient(AgentRemoteClientInfo clientInfos, bool isElevated, CancellationToken token)
|
||||
{
|
||||
string url = "api/management/c4it/phoenix-connections";
|
||||
if (isElevated)
|
||||
url += "/admin";
|
||||
|
||||
return await _agentApiHandler.Request<AgentRemoteConnectionInfo>(url, HTTP.eHttpMethod.post, clientInfos, token);
|
||||
}
|
||||
|
||||
public async Task TerminateConnection(Guid connectionId)
|
||||
{
|
||||
await _agentApiHandler.Request($"api/management/c4it/phoenix-connections/{connectionId}", HTTP.eHttpMethod.delete);
|
||||
}
|
||||
|
||||
public bool IsActive() => true;
|
||||
|
||||
public Task<HealthInformation> GetHealthInfo()
|
||||
{
|
||||
// todo Agent Server has to implement an "health" endpoint and return its result
|
||||
return Task.FromResult(new HealthInformation(HealthStatus.healthy));
|
||||
}
|
||||
}
|
||||
}
|
||||
13
F4SD-Cockpit-ServerCore/Modules/Agent/DTOs/AgentErrorDto.cs
Normal file
13
F4SD-Cockpit-ServerCore/Modules/Agent/DTOs/AgentErrorDto.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent.DTOs
|
||||
{
|
||||
public class AgentErrorDto
|
||||
{
|
||||
[JsonProperty("code")]
|
||||
public string Code { get; set; }
|
||||
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent.DTOs
|
||||
{
|
||||
public class AgentLogonResultDto
|
||||
{
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[JsonProperty("expires_in")]
|
||||
public int ExpiresIn { get; set; }
|
||||
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
|
||||
[JsonProperty("scope")]
|
||||
public string Scope { get; set; }
|
||||
|
||||
[JsonProperty("remote_ip")]
|
||||
public string RemoteIp { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user