diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/App_Start/IocConfig.cs b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/App_Start/IocConfig.cs index f1be507..a655512 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/App_Start/IocConfig.cs +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/App_Start/IocConfig.cs @@ -1,5 +1,6 @@ using Autofac; using Autofac.Integration.WebApi; +using LCU.API.Internal.CoreSoapApiWrapper.Configuration; using LCU.API.Internal.CoreSoapApiWrapper.CoreSoapUtilities; using LCU.API.Internal.CoreSoapApiWrapper.DataAccess; using LCU.API.Internal.CoreSoapApiWrapper.Models; @@ -39,7 +40,7 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.App_Start RegisterSoapClasses(builder); // Get apikey from secret file if available, otherwise fallback to appsettings - var seqApiKey = ConfigurationManager.AppSettings["serilog:write-to:Seq.apiKey"]; + var seqApiKey = AppSettingsResolver.Get("serilog:write-to:Seq.apiKey"); try { seqApiKey = File.ReadAllText("/vault/secrets/core-soap-api-wrapper-api-seq-api-key.json").Trim(); @@ -52,7 +53,7 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.App_Start { return new LoggerConfiguration().Enrich.FromLogContext() .Enrich.With() - .WriteTo.Seq(ConfigurationManager.AppSettings["serilog:write-to:Seq.serverUrl"], LogEventLevel.Information, 1000, null, seqApiKey) + .WriteTo.Seq(AppSettingsResolver.Get("serilog:write-to:Seq.serverUrl"), LogEventLevel.Information, 1000, null, seqApiKey) .CreateLogger(); }).SingleInstance(); @@ -86,4 +87,4 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.App_Start builder.RegisterType().As(); } } -} \ No newline at end of file +} diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Attributes/ApiKeyAuthorizeAttribute.cs b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Attributes/ApiKeyAuthorizeAttribute.cs index 5090253..67978d5 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Attributes/ApiKeyAuthorizeAttribute.cs +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Attributes/ApiKeyAuthorizeAttribute.cs @@ -1,7 +1,7 @@ -using Serilog; +using LCU.API.Internal.CoreSoapApiWrapper.Configuration; +using Serilog; using System; using System.Collections.Generic; -using System.Configuration; using System.IO; using System.Linq; using System.Net; @@ -22,11 +22,7 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Attributes public ApiKeyAuthorizeAttribute() { - _externalApiKeySet = ConfigurationManager.AppSettings.AllKeys - .Where(k => k.StartsWith(KeySetPrefix)) - .ToDictionary( - k => k.Substring(KeySetPrefix.Length), - k => ConfigurationManager.AppSettings[k]); + _externalApiKeySet = AppSettingsResolver.GetByPrefix(KeySetPrefix); try { @@ -37,7 +33,7 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Attributes // do nothing, fallback to appsettings value if secret file is not found or cannot be read } - _authenticationFailureBehavior = ConfigurationManager.AppSettings["ApiSecurityConfiguration:ApiKeyAuthenticationFailureBehavior"] ?? "Error"; + _authenticationFailureBehavior = AppSettingsResolver.Get("ApiSecurityConfiguration:ApiKeyAuthenticationFailureBehavior") ?? "Error"; } protected override bool IsAuthorized(HttpActionContext actionContext) @@ -84,4 +80,4 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Attributes }; } } -} \ No newline at end of file +} diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Configuration/AppSettingsResolver.cs b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Configuration/AppSettingsResolver.cs new file mode 100644 index 0000000..4fddbc6 --- /dev/null +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Configuration/AppSettingsResolver.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Xml.Linq; + +namespace LCU.API.Internal.CoreSoapApiWrapper.Configuration +{ + public static class AppSettingsResolver + { + private const string ExternalAppSettingsPath = "/app/config/environment-appsettings/appsettings.config"; + + private static readonly Lazy> ExternalSettings = + new Lazy>(LoadExternalSettings); + + public static string Get(string key) + { + if (ExternalSettings.Value.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value)) + { + return value; + } + + return ConfigurationManager.AppSettings[key]; + } + + public static Dictionary GetByPrefix(string prefix) + { + var mergedSettings = new Dictionary(StringComparer.OrdinalIgnoreCase); + var appSettings = ConfigurationManager.AppSettings; + + foreach (var key in appSettings.AllKeys.Where(k => k != null && k.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) + { + mergedSettings[key.Substring(prefix.Length)] = appSettings[key]; + } + + foreach (var kvp in ExternalSettings.Value.Where(kvp => kvp.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) + { + mergedSettings[kvp.Key.Substring(prefix.Length)] = kvp.Value; + } + + return mergedSettings; + } + + private static IReadOnlyDictionary LoadExternalSettings() + { + try + { + if (!File.Exists(ExternalAppSettingsPath)) + { + return new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + var document = XDocument.Load(ExternalAppSettingsPath); + + return document.Root? + .Elements("add") + .Where(element => element.Attribute("key") != null) + .ToDictionary( + element => element.Attribute("key").Value, + element => element.Attribute("value")?.Value, + StringComparer.OrdinalIgnoreCase) + ?? new Dictionary(StringComparer.OrdinalIgnoreCase); + } + catch (Exception) + { + return new Dictionary(StringComparer.OrdinalIgnoreCase); + } + } + } +} diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Controllers/StatusController.cs b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Controllers/StatusController.cs index f91ab5a..7b5654e 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Controllers/StatusController.cs +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Controllers/StatusController.cs @@ -1,7 +1,7 @@ using System; -using System.Configuration; using System.Web.Http; using Serilog; +using LCU.API.Internal.CoreSoapApiWrapper.Configuration; using LCU.API.Internal.CoreSoapApiWrapper.Models; namespace LCU.API.Internal.CoreSoapApiWrapper.Controllers @@ -21,7 +21,7 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Controllers var result = new EnvironmentView(); result.Application = "LCU.API.Internal.CoreSoapApiWrapper"; result.CurrentDate = DateTime.Now; - result.Environment = ConfigurationManager.AppSettings["KnownEnvironment"]; + result.Environment = AppSettingsResolver.Get("KnownEnvironment"); Log.Verbose($"{result.Application}'s status endpoint was hit in {result.Environment}"); return Ok(result); } diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/CoreSoapUtilities/CoreSoapRequest.cs b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/CoreSoapUtilities/CoreSoapRequest.cs index dbb75f9..9c28d7b 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/CoreSoapUtilities/CoreSoapRequest.cs +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/CoreSoapUtilities/CoreSoapRequest.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ServiceModel; using LCU.API.Internal.CoreSoapApiWrapper.Models; namespace LCU.API.Internal.CoreSoapApiWrapper.CoreSoapUtilities @@ -44,7 +45,9 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.CoreSoapUtilities private TransactionOutput SubmitTransactionInput(TransactionInput transactionInput) { - var client = new CoreApiServiceClient(_soapConfiguration.Endpoint); + var client = string.IsNullOrWhiteSpace(_soapConfiguration.CoreApiServiceUrl) + ? new CoreApiServiceClient(_soapConfiguration.Endpoint) + : new CoreApiServiceClient(_soapConfiguration.Endpoint, new EndpointAddress(_soapConfiguration.CoreApiServiceUrl)); TransactionOutput output = client.SubmitRequest(transactionInput); if (output?.Output?.UserAuthentication == null || output?.Output?.Responses == null) @@ -60,4 +63,4 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.CoreSoapUtilities return output; } } -} \ No newline at end of file +} diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper.csproj b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper.csproj index cf6fe83..a6ebb69 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper.csproj +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper.csproj @@ -181,6 +181,7 @@ + @@ -336,4 +337,4 @@ --> - \ No newline at end of file + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Models/SoapConfiguration.cs b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Models/SoapConfiguration.cs index e6df019..f593d82 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Models/SoapConfiguration.cs +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Models/SoapConfiguration.cs @@ -1,4 +1,5 @@ -using System; +using LCU.API.Internal.CoreSoapApiWrapper.Configuration; +using System; using System.Configuration; using System.IO; @@ -10,25 +11,26 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Models { int defaultValue; - SafUrl = ConfigurationManager.AppSettings["soapconnection:safUrl"]; - DeviceId = ConfigurationManager.AppSettings["soapconnection:deviceId"]; - UserId = ReadSecret("/vault/secrets/core-soap-api-wrapper-soap-connection-user-id.json") ?? ConfigurationManager.AppSettings["soapconnection:userId"]; - Password = ReadSecret("/vault/secrets/core-soap-api-wrapper-soap-connection-password.json") ?? ConfigurationManager.AppSettings["soapconnection:password"]; - EnvironmentCode = ConfigurationManager.AppSettings["soapconnection:prodEnvCd"]; - DefCode = ConfigurationManager.AppSettings["soapconnection:prodDefCd"]; - ApplicationId = ConfigurationManager.AppSettings["soapconnection:applId"]; - Endpoint = ConfigurationManager.AppSettings["soapconnection:endpoint"]; - ApprovalPersonNumber = ConfigurationManager.AppSettings["soapconnection:approvalpersonnumber"]; - OverrideCashBoxNumber = ConfigurationManager.AppSettings["soapconnection:overridecashboxnumber"]; - SocketDeviceId = ConfigurationManager.AppSettings["socketconnection:deviceId"]; - SocketApplicationId = ConfigurationManager.AppSettings["socketconnection:applId"]; - SocketUserId = ReadSecret("/vault/secrets/core-soap-api-wrapper-socket-connection-user-id.json") ?? ConfigurationManager.AppSettings["socketconnection:userId"]; - SocketPassword = ReadSecret("/vault/secrets/core-soap-api-wrapper-socket-connection-password.json") ?? ConfigurationManager.AppSettings["socketconnection:password"]; - SocketTimeout = int.TryParse(ConfigurationManager.AppSettings["socketconnection:timeout"], out defaultValue) ? defaultValue : 10000; - IPAddress = ConfigurationManager.AppSettings["socketconnection:ipAddress"]; - PortId = int.TryParse(ConfigurationManager.AppSettings["socketconnection:portId"], out defaultValue) ? defaultValue : 2503; - RequestType = ConfigurationManager.AppSettings["socketconnection:reqType"]; - AuthenticationType = ConfigurationManager.AppSettings["socketconnection:authType"]; + SafUrl = AppSettingsResolver.Get("soapconnection:safUrl"); + DeviceId = AppSettingsResolver.Get("soapconnection:deviceId"); + UserId = ReadSecret("/vault/secrets/core-soap-api-wrapper-soap-connection-user-id.json") ?? AppSettingsResolver.Get("soapconnection:userId"); + Password = ReadSecret("/vault/secrets/core-soap-api-wrapper-soap-connection-password.json") ?? AppSettingsResolver.Get("soapconnection:password"); + EnvironmentCode = AppSettingsResolver.Get("soapconnection:prodEnvCd"); + DefCode = AppSettingsResolver.Get("soapconnection:prodDefCd"); + ApplicationId = AppSettingsResolver.Get("soapconnection:applId"); + Endpoint = AppSettingsResolver.Get("soapconnection:endpoint"); + CoreApiServiceUrl = AppSettingsResolver.Get("soapconnection:coreApiServiceUrl"); + ApprovalPersonNumber = AppSettingsResolver.Get("soapconnection:approvalpersonnumber"); + OverrideCashBoxNumber = AppSettingsResolver.Get("soapconnection:overridecashboxnumber"); + SocketDeviceId = AppSettingsResolver.Get("socketconnection:deviceId"); + SocketApplicationId = AppSettingsResolver.Get("socketconnection:applId"); + SocketUserId = ReadSecret("/vault/secrets/core-soap-api-wrapper-socket-connection-user-id.json") ?? AppSettingsResolver.Get("socketconnection:userId"); + SocketPassword = ReadSecret("/vault/secrets/core-soap-api-wrapper-socket-connection-password.json") ?? AppSettingsResolver.Get("socketconnection:password"); + SocketTimeout = int.TryParse(AppSettingsResolver.Get("socketconnection:timeout"), out defaultValue) ? defaultValue : 10000; + IPAddress = AppSettingsResolver.Get("socketconnection:ipAddress"); + PortId = int.TryParse(AppSettingsResolver.Get("socketconnection:portId"), out defaultValue) ? defaultValue : 2503; + RequestType = AppSettingsResolver.Get("socketconnection:reqType"); + AuthenticationType = AppSettingsResolver.Get("socketconnection:authType"); string ReadSecret(string path) { @@ -54,6 +56,7 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Models public string DefCode { get; set; } public string ApplicationId { get; set; } public string Endpoint { get; set; } + public string CoreApiServiceUrl { get; set; } public string ApprovalPersonNumber { get; set; } public string OverrideCashBoxNumber { get; set; } public string SocketDeviceId { get; set; } @@ -66,4 +69,4 @@ namespace LCU.API.Internal.CoreSoapApiWrapper.Models public string RequestType { get; set; } public string AuthenticationType { get; set; } } -} \ No newline at end of file +} diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Debug.config b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Debug.config index 252eb2a..3d2f928 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Debug.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Debug.config @@ -20,6 +20,7 @@ + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Release.config b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Release.config index 5fff49e..34701ca 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Release.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Release.config @@ -23,6 +23,7 @@ + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Uat.config b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Uat.config index 68dc77e..eb107e9 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Uat.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.Uat.config @@ -23,6 +23,7 @@ + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.config b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.config index 452f934..3555751 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/LCU.API.Internal.CoreSoapApiWrapper/Web.config @@ -35,6 +35,7 @@ + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/prd/appsettings/appsettings.config b/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/prd/appsettings/appsettings.config index 20c938a..647805f 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/prd/appsettings/appsettings.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/prd/appsettings/appsettings.config @@ -15,6 +15,7 @@ + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/qa/appsettings/appsettings.config b/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/qa/appsettings/appsettings.config index 8260a2d..a3691ba 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/qa/appsettings/appsettings.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/qa/appsettings/appsettings.config @@ -15,6 +15,7 @@ + diff --git a/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/uat/appsettings/appsettings.config b/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/uat/appsettings/appsettings.config index f1c8a4c..10cacb4 100644 --- a/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/uat/appsettings/appsettings.config +++ b/LCU.API.Internal.CoreSoapApiWrapper/kustomize/overlays/uat/appsettings/appsettings.config @@ -15,6 +15,7 @@ +