diff --git a/function-app/adb-to-purview/src/Function.Domain/Constants/FeatureFlags.cs b/function-app/adb-to-purview/src/Function.Domain/Constants/FeatureFlags.cs index b22e94b..85ed595 100644 --- a/function-app/adb-to-purview/src/Function.Domain/Constants/FeatureFlags.cs +++ b/function-app/adb-to-purview/src/Function.Domain/Constants/FeatureFlags.cs @@ -6,6 +6,10 @@ public static class FeatureFlags public static class Logging { public const string LogOlMessageToExternalStore = "LogOlMessageToExternalStore"; - } + } + public static class Security + { + public const string ValidateHttpOlSourceHeader = "ValidateHttpOlSourceHeader"; + } } } \ No newline at end of file diff --git a/function-app/adb-to-purview/src/Function.Domain/Helpers/HttpHelper.cs b/function-app/adb-to-purview/src/Function.Domain/Helpers/HttpHelper.cs index 5596aeb..098655b 100644 --- a/function-app/adb-to-purview/src/Function.Domain/Helpers/HttpHelper.cs +++ b/function-app/adb-to-purview/src/Function.Domain/Helpers/HttpHelper.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using System.Net; using Microsoft.Azure.Functions.Worker.Http; +using System.Linq; namespace Function.Domain.Helpers { @@ -19,5 +20,20 @@ public HttpResponseData CreateServerErrorHttpResponse(HttpRequestData req) return response; } + + public HttpResponseData CreateUnauthorizedHttpResponse(HttpRequestData req) + { + var response = req.CreateResponse(HttpStatusCode.Forbidden); + return response; + } + + public bool ValidateRequestHeaders(HttpRequestData req, string sourceHeaderExpectedValue) + { + if (req.Headers.TryGetValues("x-teladoc-udf-ol-source", out var values)) + { + return values.Contains(sourceHeaderExpectedValue, System.StringComparer.OrdinalIgnoreCase); + } + return false; + } } } \ No newline at end of file diff --git a/function-app/adb-to-purview/src/Function.Domain/Helpers/IHttpHelper.cs b/function-app/adb-to-purview/src/Function.Domain/Helpers/IHttpHelper.cs index 4754efb..dd55f4e 100644 --- a/function-app/adb-to-purview/src/Function.Domain/Helpers/IHttpHelper.cs +++ b/function-app/adb-to-purview/src/Function.Domain/Helpers/IHttpHelper.cs @@ -7,5 +7,7 @@ public interface IHttpHelper { public Task CreateSuccessfulHttpResponse(HttpRequestData req, object data); public HttpResponseData CreateServerErrorHttpResponse(HttpRequestData req); + public HttpResponseData CreateUnauthorizedHttpResponse(HttpRequestData req); + public bool ValidateRequestHeaders(HttpRequestData req, string sourceHeaderExpectedValue); } } \ No newline at end of file diff --git a/function-app/adb-to-purview/src/Functions/OpenLineageIn.cs b/function-app/adb-to-purview/src/Functions/OpenLineageIn.cs index b78f72b..40977e8 100644 --- a/function-app/adb-to-purview/src/Functions/OpenLineageIn.cs +++ b/function-app/adb-to-purview/src/Functions/OpenLineageIn.cs @@ -54,7 +54,7 @@ public OpenLineageIn( [Function("OpenLineageIn")] public async Task Run( [HttpTrigger( - AuthorizationLevel.Function, + AuthorizationLevel.Anonymous, "get", "post", Route = "v1/lineage" @@ -63,15 +63,24 @@ public async Task Run( try { _logger.LogInformation($"OpenLineageIn: Processing request..."); + + // Validate request headers + if (!_httpHelper.ValidateRequestHeaders(req, _configuration["OlSourceHeaderExpectedValue"] ?? Guid.NewGuid().ToString())) + { + return _httpHelper.CreateUnauthorizedHttpResponse(req); + } + // send event data to EventHub var events = new List(); - var strRequest = await req.ReadAsStringAsync(); + + // Validate body is not empty if (string.IsNullOrEmpty(strRequest)) { throw new Exception("OpenLineageIn: Request is null or empty."); } + // Validate body is OpenLineage message if (_olFilter.FilterOlMessage(strRequest)) { _logger.LogInformation($"OpenLineageIn: Request passed validation.");