コード例 #1
0
ファイル: TraceMiddleware.cs プロジェクト: shubDhond/KuduLite
        private static void LogBeginRequest(HttpContext httpContext)
        {
            if (whiteListedPaths.FindIndex(x => x.Contains(httpContext.Request.Path.ToString(),
                                                           StringComparison.OrdinalIgnoreCase)) != -1)
            {
                return;
            }

            OperationManager.SafeExecute(() =>
            {
                var request   = httpContext.Request;
                var requestId = request.GetRequestId() ?? Guid.NewGuid().ToString();
                httpContext.Items[Constants.RequestIdHeader]    = requestId;
                httpContext.Items[Constants.RequestDateTimeUtc] = DateTime.UtcNow;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "OnBeginRequest",
                    GetRawUrl(request),
                    request.Method,
                    requestId,
                    0,
                    0,
                    request.GetUserAgent());
            });
        }
コード例 #2
0
        private async Task Assign(HostAssignmentContext assignmentContext)
        {
            try
            {
                // first make all environment and file system changes required for
                // the host to be specialized
                assignmentContext.ApplyAppSettings();

                KuduEventGenerator.Log(null).LogMessage(EventLevel.Informational, assignmentContext.SiteName,
                                                        $"Mounting file share at {DateTime.UtcNow}", string.Empty);

                // Limit the amount of time time we allow for mounting to complete
                var mounted = await MountFileShareWithin(TimeSpan.FromSeconds(30));

                KuduEventGenerator.Log(null).LogMessage(EventLevel.Informational, assignmentContext.SiteName,
                                                        $"Mount file share result: {mounted} at {DateTime.UtcNow}", string.Empty);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                // all assignment settings/files have been applied so we can flip
                // the switch now on specialization
                // even if there are failures applying context above, we want to
                // leave placeholder mode
                _linuxConsumptionEnv.FlagAsSpecializedAndReady();
                _linuxConsumptionEnv.ResumeRequests();
            }
        }
コード例 #3
0
        private async Task <string> MountKuduFileShare(string siteName, string connectionString)
        {
            try
            {
                var fileShareName = string.Format(FileShareFormat, Constants.KuduFileSharePrefix,
                                                  ServerConfiguration.GetApplicationName().ToLowerInvariant());

                await _storageClient.CreateFileShare(siteName, connectionString, fileShareName);

                KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Informational, siteName,
                                                                $"Mounting Kudu mount file share {fileShareName} at {Constants.KuduFileShareMountPath}",
                                                                string.Empty);

                await _meshServiceClient.MountCifs(connectionString, fileShareName, Constants.KuduFileShareMountPath);

                return(string.Empty);
            }
            catch (Exception e)
            {
                var message = e.ToString();
                KuduEventGenerator.Log(_environment)
                .LogMessage(EventLevel.Warning, siteName, nameof(MountKuduFileShare), message);
                return(message);
            }
        }
コード例 #4
0
ファイル: TraceMiddleware.cs プロジェクト: shubDhond/KuduLite
        private static void LogEndRequest(HttpContext httpContext)
        {
            if (whiteListedPaths.FindIndex(x => x.Contains(httpContext.Request.Path.ToString(),
                                                           StringComparison.OrdinalIgnoreCase)) != -1)
            {
                return;
            }

            OperationManager.SafeExecute(() =>
            {
                var request               = httpContext.Request;
                var response              = httpContext.Response;
                var requestId             = (string)httpContext.Items[Constants.RequestIdHeader];
                var requestTime           = (DateTime)httpContext.Items[Constants.RequestDateTimeUtc];
                var latencyInMilliseconds = (long)(DateTime.UtcNow - requestTime).TotalMilliseconds;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "OnEndRequest",
                    GetRawUrl(request),
                    request.Method,
                    requestId,
                    response.StatusCode,
                    latencyInMilliseconds,
                    request.GetUserAgent());
            });
        }
コード例 #5
0
        public void ReturnsLinuxEventGenerator()
        {
            var environment = new TestSystemEnvironment();

            environment.SetEnvironmentVariable(Constants.ContainerName, "container-name");

            var eventGenerator = KuduEventGenerator.Log(environment);

            Assert.True(eventGenerator is LinuxContainerEventGenerator);
        }
コード例 #6
0
        private static async Task PrintRequirementsTxtDependenciesAsync(string builtFolder)
        {
            string filename            = "requirements.txt";
            string requirementsTxtPath = Path.Combine(builtFolder, filename);

            if (File.Exists(requirementsTxtPath))
            {
                string[] lines = await File.ReadAllLinesAsync(requirementsTxtPath);

                foreach (string line in lines)
                {
                    int separatorIndex;
                    if (line.IndexOf("==") >= 0)
                    {
                        separatorIndex = line.IndexOf("==");
                    }
                    else if (line.IndexOf(">=") >= 0)
                    {
                        separatorIndex = line.IndexOf(">=");
                    }
                    else if (line.IndexOf("<=") >= 0)
                    {
                        separatorIndex = line.IndexOf("<=");
                    }
                    else if (line.IndexOf(">") >= 0)
                    {
                        separatorIndex = line.IndexOf(">");
                    }
                    else if (line.IndexOf("<") >= 0)
                    {
                        separatorIndex = line.IndexOf("<");
                    }
                    else
                    {
                        separatorIndex = line.Length;
                    }

                    string package = line.Substring(0, separatorIndex).Trim();
                    string version = line.Substring(separatorIndex).Trim();

                    KuduEventGenerator.Log().GenericEvent(
                        ServerConfiguration.GetApplicationName(),
                        $"dependencies,python,{filename},{package},{version}",
                        Guid.Empty.ToString(),
                        string.Empty,
                        string.Empty,
                        string.Empty);
                }
            }
        }
コード例 #7
0
        private async Task <HttpResponseMessage> SendAsync(IEnumerable <KeyValuePair <string, string> > formData)
        {
            var operationName = formData.FirstOrDefault(f => string.Equals(f.Key, Operation)).Value;
            var meshUri       = _environment.GetEnvironmentVariable(Constants.MeshInitURI);

            KuduEventGenerator.Log(_environment).GenericEvent(ServerConfiguration.GetApplicationName(),
                                                              $"Sending mesh request {operationName} to {meshUri}", string.Empty, string.Empty, string.Empty, string.Empty);

            var res = await _client.PostAsync(meshUri, new FormUrlEncodedContent(formData));

            KuduEventGenerator.Log(_environment).GenericEvent(ServerConfiguration.GetApplicationName(),
                                                              $"Mesh response {res.StatusCode}", string.Empty, string.Empty, string.Empty, string.Empty);
            return(res);
        }
コード例 #8
0
 private bool EnsureMountedDeploymentsPath(string path)
 {
     try
     {
         FileSystemHelpers.EnsureDirectory(path);
         return(true);
     }
     catch (Exception e)
     {
         KuduEventGenerator.Log().LogMessage(EventLevel.Informational, ServerConfiguration.GetApplicationName(),
                                             $"{nameof(EnsureMountedDeploymentsPath)} Failed. Path = {path}", e.ToString());
         return(false);
     }
 }
コード例 #9
0
ファイル: TraceMiddleware.cs プロジェクト: shubDhond/KuduLite
        private static ITracer TraceStartup(HttpContext httpContext)
        {
            ITracer tracer = null;

            // 0 means this is the very first request starting up Kudu
            if (0 == Interlocked.Exchange(ref _traceStartup, 1))
            {
                tracer = TraceServices.CreateRequestTracer(httpContext);

                if (tracer != null && tracer.TraceLevel > TraceLevel.Off)
                {
                    var attribs = GetTraceAttributes(httpContext);

                    // force always trace
                    attribs[TraceExtensions.AlwaysTrace] = "1";

                    // Dump environment variables
                    foreach (DictionaryEntry entry in System.Environment.GetEnvironmentVariables())
                    {
                        var key = (string)entry.Key;
                        if (key.StartsWith("SCM", StringComparison.OrdinalIgnoreCase))
                        {
                            attribs[key] = (string)entry.Value;
                        }
                    }

                    tracer.Trace(XmlTracer.StartupRequestTrace, attribs);
                }

                OperationManager.SafeExecute(() =>
                {
                    var requestId = (string)httpContext.Items[Constants.RequestIdHeader];
                    var assembly  = Assembly.GetExecutingAssembly();
                    var fvi       = FileVersionInfo.GetVersionInfo(assembly.Location);
                    KuduEventGenerator.Log().GenericEvent(
                        ServerConfiguration.GetApplicationName(),
                        string.Format("StartupRequest pid:{0}, domain:{1}", Process.GetCurrentProcess().Id,
                                      AppDomain.CurrentDomain.Id),
                        requestId,
                        System.Environment.GetEnvironmentVariable(SettingsKeys.ScmType),
                        System.Environment.GetEnvironmentVariable(SettingsKeys.WebSiteSku),
                        fvi.FileVersion);
                });
            }

            return(tracer);
        }
コード例 #10
0
        /// <summary>
        /// Mounts file share
        /// </summary>
        /// <returns></returns>
        public async Task <bool> MountFileShare()
        {
            var siteName = ServerConfiguration.GetApplicationName();

            if (IsKuduShareMounted())
            {
                const string message = "Kudu file share mounted already";
                UpdateStatus(true, message);
                KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Warning, siteName, nameof(MountFileShare), message);
                return(true);
            }

            if (!_environment.IsOnLinuxConsumption())
            {
                const string message =
                    "Mounting kudu file share is only supported on Linux consumption environment";
                UpdateStatus(false, message);
                KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Warning, siteName, nameof(MountFileShare), message);
                return(false);
            }

            if (!IsPersistentStorageEnabled())
            {
                const string message = "Kudu file share was not mounted since persistent storage is disabled";
                UpdateStatus(false, message);
                KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Warning, siteName, nameof(MountFileShare), message);
                return(false);
            }

            if (!TryGetStorageConnectionString(out var connectionString))
            {
                var message = $"Kudu file share was not mounted since {Constants.AzureWebJobsStorage} is empty";
                UpdateStatus(false, message);
                KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Warning, siteName, nameof(MountFileShare), message);
                return(false);
            }

            var errorMessage = await MountKuduFileShare(siteName, connectionString);

            var mountResult = string.IsNullOrEmpty(errorMessage);

            UpdateStatus(mountResult, errorMessage);
            KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Informational, siteName,
                                                            $"Mounting Kudu file share result: {mountResult}", string.Empty);

            return(mountResult);
        }
コード例 #11
0
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
        {
            if (_logger != null && eventType <= TraceEventType.Information)
            {
                _logger.Log(format, args);

                KuduEventGenerator.Log().GenericEvent(
                    ServerConfiguration.GetApplicationName(),
                    string.Format(format, args),
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    string.Empty,
                    string.Empty,
                    string.Empty);
            }

            _tracer.Trace(format, args);
        }
コード例 #12
0
        private static async Task LogDependenciesFile(string builtFolder)
        {
            try
            {
                await PrintRequirementsTxtDependenciesAsync(builtFolder);
                await PrintPackageJsonDependenciesAsync(builtFolder);

                PrintCsprojDependenciesAsync(builtFolder);
            } catch (Exception)
            {
                KuduEventGenerator.Log().GenericEvent(
                    ServerConfiguration.GetApplicationName(),
                    $"dependencies,failed to parse function app dependencies",
                    Guid.Empty.ToString(),
                    string.Empty,
                    string.Empty,
                    string.Empty);
            }
        }
コード例 #13
0
 private static void LogBeginRequest(HttpContext httpContext)
 {
     OperationManager.SafeExecute(() =>
     {
         var request   = httpContext.Request;
         var requestId = request.GetRequestId() ?? Guid.NewGuid().ToString();
         httpContext.Items[Constants.RequestIdHeader]    = requestId;
         httpContext.Items[Constants.RequestDateTimeUtc] = DateTime.UtcNow;
         KuduEventGenerator.Log().ApiEvent(
             ServerConfiguration.GetApplicationName(),
             "OnBeginRequest",
             GetRawUrl(request),
             request.Method,
             requestId,
             0,
             0,
             request.GetUserAgent());
     });
 }
コード例 #14
0
 private static void LogEndRequest(HttpContext httpContext)
 {
     OperationManager.SafeExecute(() =>
     {
         var request               = httpContext.Request;
         var response              = httpContext.Response;
         var requestId             = (string)httpContext.Items[Constants.RequestIdHeader];
         var requestTime           = (DateTime)httpContext.Items[Constants.RequestDateTimeUtc];
         var latencyInMilliseconds = (long)(DateTime.UtcNow - requestTime).TotalMilliseconds;
         KuduEventGenerator.Log().ApiEvent(
             ServerConfiguration.GetApplicationName(),
             "OnEndRequest",
             GetRawUrl(request),
             request.Method,
             requestId,
             response.StatusCode,
             latencyInMilliseconds,
             request.GetUserAgent());
     });
 }
コード例 #15
0
        private static async Task PrintPackageJsonDependenciesAsync(string builtFolder)
        {
            string filename        = "package.json";
            string packageJsonPath = Path.Combine(builtFolder, filename);

            if (File.Exists(packageJsonPath))
            {
                string content = await File.ReadAllTextAsync(packageJsonPath);

                JObject jobj = JObject.Parse(content);
                if (jobj.ContainsKey("devDependencies"))
                {
                    Dictionary <string, string> dictObj = jobj["devDependencies"].ToObject <Dictionary <string, string> >();
                    foreach (string key in dictObj.Keys)
                    {
                        KuduEventGenerator.Log().GenericEvent(
                            ServerConfiguration.GetApplicationName(),
                            $"dependencies,node,{filename},{key},{dictObj[key]},devDependencies",
                            Guid.Empty.ToString(),
                            string.Empty,
                            string.Empty,
                            string.Empty);
                    }
                }

                if (jobj.ContainsKey("dependencies"))
                {
                    Dictionary <string, string> dictObj = jobj["dependencies"].ToObject <Dictionary <string, string> >();
                    foreach (string key in dictObj.Keys)
                    {
                        KuduEventGenerator.Log().GenericEvent(
                            ServerConfiguration.GetApplicationName(),
                            $"dependencies,node,{filename},{key},{dictObj[key]},dependencies",
                            Guid.Empty.ToString(),
                            string.Empty,
                            string.Empty,
                            string.Empty);
                    }
                }
            }
        }
コード例 #16
0
        private async Task <bool> MountFileShareWithin(TimeSpan timeLimit)
        {
            var startTime = DateTime.UtcNow;

            try
            {
                return(await OperationManager.ExecuteWithTimeout(MountFileShare(), timeLimit));
            }
            catch (Exception e)
            {
                KuduEventGenerator.Log(null).LogMessage(EventLevel.Warning, ServerConfiguration.GetApplicationName(),
                                                        nameof(MountFileShareWithin), e.ToString());
                return(false);
            }
            finally
            {
                KuduEventGenerator.Log(null).LogMessage(EventLevel.Informational,
                                                        ServerConfiguration.GetApplicationName(),
                                                        $"Time taken to mount = {(DateTime.UtcNow - startTime).TotalMilliseconds}", string.Empty);
            }
        }
コード例 #17
0
        public async Task CreateFileShare(string siteName, string connectionString, string fileShareName)
        {
            try
            {
                var storageAccount = CloudStorageAccount.Parse(connectionString);
                var fileClient     = storageAccount.CreateCloudFileClient();

                // Get a reference to the file share we created previously.
                CloudFileShare share = fileClient.GetShareReference(fileShareName);

                KuduEventGenerator.Log(_environment).LogMessage(EventLevel.Informational, siteName,
                                                                $"Creating Kudu mount file share {fileShareName}", string.Empty);

                await share.CreateIfNotExistsAsync(new FileRequestOptions(), new OperationContext());
            }
            catch (Exception e)
            {
                KuduEventGenerator.Log(_environment)
                .LogMessage(EventLevel.Warning, siteName, nameof(CreateFileShare), e.ToString());
                throw;
            }
        }
コード例 #18
0
ファイル: TraceMiddleware.cs プロジェクト: shubDhond/KuduLite
        private static void TraceHeartbeat()
        {
            var now = DateTime.UtcNow;

            if (_nextHeartbeatDateTime >= now)
            {
                return;
            }
            _nextHeartbeatDateTime = now.AddHours(1);

            OperationManager.SafeExecute(() =>
            {
                KuduEventGenerator.Log().GenericEvent(
                    ServerConfiguration.GetApplicationName(),
                    string.Format("Heartbeat pid:{0}, domain:{1}", Process.GetCurrentProcess().Id,
                                  AppDomain.CurrentDomain.Id),
                    string.Empty,
                    System.Environment.GetEnvironmentVariable(SettingsKeys.ScmType),
                    System.Environment.GetEnvironmentVariable(SettingsKeys.WebSiteSku),
                    KuduVersion.Value);
            });
        }
コード例 #19
0
 private static void PrintCsprojDependenciesAsync(string builtFolder)
 {
     foreach (string csprojPath in Directory.GetFiles(builtFolder, "*.csproj", SearchOption.TopDirectoryOnly))
     {
         string   filename      = Path.GetFileName(csprojPath);
         XElement purchaseOrder = XElement.Load(csprojPath);
         foreach (var itemGroup in purchaseOrder.Elements("ItemGroup"))
         {
             foreach (var packageReference in itemGroup.Elements("PackageReference"))
             {
                 string include = packageReference.Attribute("Include").Value;
                 string version = packageReference.Attribute("Version").Value;
                 KuduEventGenerator.Log().GenericEvent(
                     ServerConfiguration.GetApplicationName(),
                     $"dependencies,dotnet,{filename},{include},{version}",
                     Guid.Empty.ToString(),
                     string.Empty,
                     string.Empty,
                     string.Empty);
             }
         }
     }
 }
コード例 #20
0
        /// <summary>
        /// Detect if a route matches any of whitelisted prefixes
        /// </summary>
        /// <param name="context">Http request context</param>
        /// <param name="authorizationService">Authorization service for each request</param>
        /// <returns>Response be set to 404 if the route is not whitelisted</returns>
        public async Task Invoke(HttpContext context, IAuthorizationService authorizationService = null)
        {
            DateTime requestTime = DateTime.UtcNow;

            // Step 1: if disguise host exists, replace the request header HOST to DISGUISED-HOST
            //         if disguist host does not exist, check and replace ~1 with regex
            if (context.Request.Headers.TryGetValue(DisguisedHostHeader, out StringValues value))
            {
                context.Request.Headers[HostHeader] = value;
            }
            else
            {
                context.Request.Host = new HostString(SanitizeScmUrl(
                                                          context.Request.Headers[HostHeader].FirstOrDefault()));
            }

            if (context.Request.Headers.TryGetValue(ForwardedProtocolHeader, out value))
            {
                context.Request.Scheme = value;
            }

            // Step 2: check if the request endpoint is enabled in Linux Consumption
            if (!IsRouteAllowed(context.Request.Path))
            {
                context.Response.StatusCode = 404;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "BlacklistedLinuxConsumptionEndpoint",
                    context.Request.GetEncodedPathAndQuery(),
                    context.Request.Method,
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    context.Response.StatusCode,
                    (DateTime.UtcNow - requestTime).Milliseconds,
                    context.Request.GetUserAgent());
                return;
            }

            // Step 3: check if the request matches authorization policy
            // If the home page is requested without authentication (e.g. ControllerPing), return 200 with hint.
            // If the home page is requested with authentication (e.g. Customer Browser Access), return 200 with homepage content.
            AuthenticateResult authenticationResult = await context.AuthenticateAsync(ArmAuthenticationDefaults.AuthenticationScheme);

            if (IsHomePageWithoutAuthentication(authenticationResult, context.Request.Path))
            {
                byte[] data = Encoding.UTF8.GetBytes("Please use /basicAuth endpoint or AAD to authenticate SCM site");
                context.Response.StatusCode  = 200;
                context.Response.ContentType = "text/plain; charset=UTF-8";
                await context.Response.Body.WriteAsync(data, 0, data.Length);

                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "AccessLinuxConsumptionHomePageWithoutAuthentication",
                    context.Request.GetEncodedPathAndQuery(),
                    context.Request.Method,
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    context.Response.StatusCode,
                    (DateTime.UtcNow - requestTime).Milliseconds,
                    context.Request.GetUserAgent());
                return;
            }
            else if (!authenticationResult.Succeeded)
            {
                context.Response.StatusCode = 401;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "UnauthenticatedLinuxConsumptionEndpoint",
                    context.Request.GetEncodedPathAndQuery(),
                    context.Request.Method,
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    context.Response.StatusCode,
                    (DateTime.UtcNow - requestTime).Milliseconds,
                    context.Request.GetUserAgent());
                return;
            }

            if (authorizationService != null)
            {
                AuthorizationResult endpointAuthorization = await authorizationService.AuthorizeAsync(authenticationResult.Principal, AuthorizationPolicy);

                if (!endpointAuthorization.Succeeded)
                {
                    context.Response.StatusCode = 401;
                    KuduEventGenerator.Log().ApiEvent(
                        ServerConfiguration.GetApplicationName(),
                        "UnauthorizedLinuxConsumptionEndpoint",
                        context.Request.GetEncodedPathAndQuery(),
                        context.Request.Method,
                        System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                        context.Response.StatusCode,
                        (DateTime.UtcNow - requestTime).Milliseconds,
                        context.Request.GetUserAgent());
                    return;
                }
            }
            await _next.Invoke(context);
        }
コード例 #21
0
        /// <summary>
        /// Detect if a route matches any of whitelisted prefixes
        /// </summary>
        /// <param name="context">Http request context</param>
        /// <param name="authorizationService">Authorization service for each request</param>
        /// <returns>Response be set to 404 if the route is not whitelisted</returns>
        public async Task Invoke(HttpContext context, IAuthorizationService authorizationService = null)
        {
            DateTime requestTime = DateTime.UtcNow;

            // Step 1: if disguise host exists, replace the request header HOST to DISGUISED-HOST
            //         if disguist host does not exist, check and replace ~1 with regex
            if (context.Request.Headers.TryGetValue(DisguisedHostHeader, out StringValues value))
            {
                context.Request.Headers[HostHeader] = value;
            }
            else
            {
                context.Request.Host = new HostString(SanitizeScmUrl(
                                                          context.Request.Headers[HostHeader].FirstOrDefault()));
            }

            if (context.Request.Headers.TryGetValue(ForwardedProtocolHeader, out value))
            {
                context.Request.Scheme = value;
            }

            // Step 2: check if it is homepage route or favicon route, always return 200
            if (IsHomePageRoute(context.Request.Path) || IsFavIconRoute(context.Request.Path))
            {
                context.Response.StatusCode = 200;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "LinuxConsumptionEndpoint",
                    context.Request.GetEncodedPathAndQuery(),
                    context.Request.Method,
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    context.Response.StatusCode,
                    (DateTime.UtcNow - requestTime).Milliseconds,
                    context.Request.GetUserAgent());
                return;
            }

            // Step 3: check if the request endpoint is enabled in Linux Consumption
            if (!IsRouteWhitelisted(context.Request.Path))
            {
                context.Response.StatusCode = 404;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "BlacklistedLinuxConsumptionEndpoint",
                    context.Request.GetEncodedPathAndQuery(),
                    context.Request.Method,
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    context.Response.StatusCode,
                    (DateTime.UtcNow - requestTime).Milliseconds,
                    context.Request.GetUserAgent());
                return;
            }

            // Step 4: check if the request matches authorization policy
            AuthenticateResult authenticationResult = await context.AuthenticateAsync(ArmAuthenticationDefaults.AuthenticationScheme);

            if (!authenticationResult.Succeeded)
            {
                context.Response.StatusCode = 401;
                KuduEventGenerator.Log().ApiEvent(
                    ServerConfiguration.GetApplicationName(),
                    "UnauthenticatedLinuxConsumptionEndpoint",
                    context.Request.GetEncodedPathAndQuery(),
                    context.Request.Method,
                    System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                    context.Response.StatusCode,
                    (DateTime.UtcNow - requestTime).Milliseconds,
                    context.Request.GetUserAgent());
                return;
            }

            if (authorizationService != null)
            {
                AuthorizationResult endpointAuthorization = await authorizationService.AuthorizeAsync(authenticationResult.Principal, AuthorizationPolicy);

                if (!endpointAuthorization.Succeeded)
                {
                    context.Response.StatusCode = 401;
                    KuduEventGenerator.Log().ApiEvent(
                        ServerConfiguration.GetApplicationName(),
                        "UnauthorizedLinuxConsumptionEndpoint",
                        context.Request.GetEncodedPathAndQuery(),
                        context.Request.Method,
                        System.Environment.GetEnvironmentVariable("x-ms-request-id") ?? string.Empty,
                        context.Response.StatusCode,
                        (DateTime.UtcNow - requestTime).Milliseconds,
                        context.Request.GetUserAgent());
                    return;
                }
            }

            await _next.Invoke(context);
        }