NLog 5.0 - Filtering Microsoft.Extensions.Logging logs doesn't work - asp.net-core

I've migrated an ASP.NET Core project from 3.1 to 6.0 and now I can't get rid of many Microsoft logs when using an Authentication middleware
For example, I always have those logs when I call my API endpoint having[Authorize(Roles = "admin")] annotation from an unauthorized client
2022-06-08 14:36:28.1023 INFO Microsoft.Extensions.Logging.LoggingExtensions.AuthenticationSchemeChallenged AuthenticationScheme: Bearer was challenged.
2022-06-08 14:40:58.7025 INFO Microsoft.Extensions.Logging.LoggingExtensions.AuthenticationSchemeChallenged AuthenticationScheme: Bearer was challenged.
2022-06-08 14:42:53.8049 INFO Microsoft.Extensions.Logging.LoggingExtensions.AuthenticationSchemeChallenged AuthenticationScheme: Bearer was challenged.
I also have those logs when calling another API using a Refit Client
2022-06-07 13:38:35.6434 INFO Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler+Log.RequestEnd Received HTTP response headers after 78.0306ms - 200
2022-06-07 13:38:35.6434 INFO Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler+Log.RequestPipelineEnd End processing HTTP request after 81.3323ms - 200
2022-06-07 13:38:35.6947 INFO Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler+Log.RequestPipelineStart Start processing HTTP request POST https://api.removed.com/endpoint
2022-06-07 13:38:35.6947 INFO Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler+Log.RequestStart Sending HTTP request POST https://api.removed.com/endpoint
2022-06-07 13:38:35.8336 INFO Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler+Log.RequestEnd Received HTTP response headers after 136.3691ms - 200
2022-06-07 13:38:35.8336 INFO Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler+Log.RequestPipelineEnd End processing HTTP request after 139.7244ms - 200
2022-06-07 13:38:35.8418 INFO Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler+Log.RequestStart Sending HTTP request POST https://api.removed.com/endpoint
2022-06-07 13:38:37.2229 INFO Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler+Log.RequestEnd Received HTTP response headers after 1379.9163ms - 200
2022-06-07 13:38:37.2229 INFO Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler+Log.RequestPipelineEnd End processing HTTP request after 2437.5144ms - 200
Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Web;
using System;
namespace CDL_CloudServerApi
{
public class Program
{
public static void Main(string[] args)
{
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
try
{
logger.Debug("Create Host");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
//NLog: catch setup errors
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseUrls("http://*:8282")
.UseStartup<Startup>()
.UseNLog();
});
}
}
nlog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off"
internalLogFile="c:\temp\nlog-internal.log">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="verbose" value="${longdate} ${uppercase:${level}} ${callsite:className=true:fileName=false:includeSourcePath=false:methodName=true:cleanNamesOfAnonymousDelegates=false:skipFrames=0} ${message}" />
<variable name="verbose_inline" value="${replace:inner=${verbose}:searchFor=\\r\\n|\\n:replaceWith=->:regex=true} ${exception:format=toString,Data:maxInnerExceptionLevel=10}"/>
<!-- 5GB max size per log-->
<targets>
<target name="logfile" xsi:type="File"
fileName="${basedir}/log/logfile.txt"
layout="${verbose_inline}"
archiveFileName="${basedir}/log/archives/log.{#}.txt"
archiveNumbering="Date"
archiveDateFormat="yyyy-MM-dd"
archiveEvery="Day"
archiveAboveSize="5000000000"
maxArchiveFiles="14"
maxArchiveDays="7"
concurrentWrites="true"
keepFileOpen="false" />
</targets>
<rules>
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" finalMinLevel="Warn" />
<logger name="System.Net.Http.*" finalMinLevel="Warn" />
<logger name="*" minlevel="Info" writeTo="logfile" />
</rules>
</nlog>

You should include ${logger} in your layout, so you can see the logger-name that should be filtered away.
<variable name="verbose" value="${longdate} ${level:uppercase=true} ${logger} ${message}" />
<variable name="verbose_inline" value="${replace-newlines:replacement=->:${verbose}} ${exception:format=toString,Data}"/>
Alternative update to minLevel="Warn" for everything:
<logger name="*" minlevel="Warn" writeTo="logfile" />
Alternative specify RemoveLoggerFactoryFilter = false for NLogProviderOptions when calling UseNLog() as mentioned in NLog 5.0 - List of major changes. Then NLog will continue to follow Microsoft Logggng Filter-configuration.
Notice that you should be careful with ${callsite}, since it introduces a huge performance overhead.
Notice that ${replace-newlines} is faster than ${replace} with regex.

Related

Remove response Server header on Azure Web App from the first redirect request to HTTPS

I’m trying to remove the response Server header from an Azure Web App ( with an ASP Net core application )
After many tries of changing the web.config and removing the header in app code using a middleware, Microsoft doesn’t give up and set the response header to Server: Microsoft-IIS/10.0 :)
The problem appears only when I’m trying to access the server on http (not https). Response code from the server is 301, and this is the only response that has the Server header.
Checking the logs I was not able to find any request to http://, and perhaps this is why I’m not able to remove header, because the request is not process in my application code.
A solution that I’m thinking is to disable the azure HTTPS only and do the redirect to https in my code (I tested and is working - server header is removed)
Is there another workaround without disabling the HTTPS only option?
Here is what I tried
Startup.cs
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.Response.Headers.Add("server", string.Empty)
}
app.UseHttpsRedirection();
}
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" />
<!-- Removes ASP.NET version header. -->
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Server" />
<remove name="X-Powered-By" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
<security>
<requestFiltering removeServerHeader="true" />
<!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
</security>
<rewrite>
<outboundRules>
<rule name="Change Server Header"> <!-- if you're not removing it completely -->
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="Unknown" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
UPDATE
When the URL of http:// is requested, IIS will process it, this time without code. So we can't control it by the code, we can only set it on the server, such as some scripts or tools. But on Azure, we have no way to directly operate as a physical server, so after exploration, I suggest that Front Door can be used to deal with this problem. Hiding server information through proxy should be a better way.
After my test, the server information is hidden, you can refer to this document . We can see from the picture that there is no 301 redirect request, and no server information in other requests.
PREVIOUS
You need to modify Global.asax.cs and Web.config file in your program.
In Global.asax.cs.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
MvcHandler.DisableMvcResponseHeader = true;
PreSendRequestHeaders += Application_PreSendRequestHeaders;
}
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
HttpContext.Current.Response.Headers.Set("Server","N/A");
}
}
And In Web.config.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" >
</modules>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>
Then u can deploy your app. After the above code modification, access to the interface or static resources can see that the server information is modified, of course, it can also be deleted by Remove.
You also can handle special event by http status code.
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
int StatusCode= HttpContext.Current.Response.StatusCode;
// handle like http status code 301
HttpContext.Current.Response.Headers.Set("Server","N/A");
}

JAX-RS writer interceptor works for every response even with NameBinding

I need to intercept a response from the server that was generated for a specific API call and change it.
I used the JAX-RS 'WriterInterceptor' for this and I have created a NameBinding as well. But the server is intercepting every response out from the server. What am I doing wrong here?
Shown below is the code I have tried. Why is the name binding does not work? (I have verified that when calling other API resources the particular method that I have use name binding is not called.)
Name Binding.
package com.example.common.cm.endpoint;
#Target({ElementType.TYPE, ElementType.METHOD})
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
public #interface JSONtoJWT {}
The Interceptor.
package com.example.common.cm.endpoint;
#Provider
#JSONtoJWT
public class TestInterceptor implements WriterInterceptor {
private static final Log log = LogFactory.getLog(TestInterceptor.class);
#Override
public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException {
log.info("interceptor invoked");
OutputStream outputStream = writerInterceptorContext.getOutputStream();
outputStream.write(("{\"message\": \"Message added in the writer interceptor in the server side\"}").getBytes());
writerInterceptorContext.setOutputStream(outputStream);
writerInterceptorContext.proceed();
log.info("Proceeded");
}
}
API Resource.
package com.example.cm.endpoint.u3.acc;
#Path("/u3/some-validation")
#Consumes({ "application/json; charset=utf-8" })
#Produces({ "application/json; charset=utf-8" })
public class SomeValidationApi {
#POST
#Path("/")
#JSONtoJWT
#Consumes({ "application/json; charset=utf-8" })
#Produces({ "application/json; charset=utf-8" })
public Response someValidationPost(#ApiParam(value = "validations post" ,required=true ) SomeValidationRequestDTO someValidationConsent)
{
return delegate.someValidationPost(someValidationConsent);
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<context:property-placeholder/>
<context:annotation-config/>
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"/>
<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"/>
<jaxrs:server id="services" address="/">
<jaxrs:serviceBeans>
***Some other beans here***
<bean class="com.example.cm.endpoint.u3.acc.SomeValidationApi/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
<bean class="com.example.common.cm.endpoint.TestInterceptor"/>
</jaxrs:providers>
</jaxrs:server>
</beans>
When I use the above every response from the server is intercepted and the message is added. But I want only the particular resource to invoke the Interceptor.
Also, Other than JAX-RS interceptor with writerInterceptor, are there any other good alternative to achieve this?

Consume soap Service in Apache Camel

i want to consume soap web serivce in apache camel using Java DSL.Any way without CXF.i have already try using CXF with spring.
Here is a simple example that used only camel http without cxf. If you need to perform some modifications of SOAP request string you can just change "constant" to something like "spel".
<setBody><constant><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<MyAction>
<myparam>ABC</myparam>
</MyAction>
</soapenv:Body>
</soapenv:Envelope>]]></constant></setBody>
<setHeader headerName="SOAPAction"><constant>MySOAPAction</constant></setHeader>
<setHeader headerName="CamelHttpMethod"><constant>POST</constant></setHeader>
<setHeader headerName="Content-Type"><constant>text/xml;charset=UTF-8</constant></setHeader>
<to uri="http://myserver:1234" />
Same with Java DSL
public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("direct:start")
.setBody(constant("")) // String SOAP content from XML example
.setHeader("SOAPAction", constant("MySOAPAction"))
.setHeader("CamelHttpMethod", constant("POST"))
.setHeader("Content-Type", constant("text/xml;charset=UTF-8"))
.to("http://myserver:1234")
.log("SOAP service called"); // Here you can process service response
}
}

Nullpointer Exception when injecting HttpRequest

I have a Liberty JAX-RS 2.0 Application on Bluemix. My goal is to use the Bluemix Session Cache Service as a central session storage.
In my interface, I inject the HttpRequest object like this:
#Path("/resource")
public class MyResource {
#Post
public Response myOperation(..., #Context final HttpServletRequest httpRequest) {
...
}
}
This runs fine with just Liberty on its own (without Session Cache Binding on Bluemix). I do not even access the httpRequest in my test app, nor do I access httpRequest.getSession(). Once I bind the Session Cache service to the Liberty App and restage the app, I get the following upon calling the API:
java.lang.NullPointerException:
at com.ibm.ws.xs.sessionmanager.IBMHttpSessionListener.attributeAdded(IBMHttpSessionListener.java:265)
at com.ibm.ws.session.http.HttpSessionAttributeObserver.sessionAttributeSet(HttpSessionAttributeObserver.java:141)
at [internal classes]
at org.jboss.weld.context.AbstractConversationContext.copyConversationIdGeneratorAndConversationsToSession(AbstractConversationContext.java:188)
at org.jboss.weld.context.AbstractConversationContext.sessionCreated(AbstractConversationContext.java:196)
at org.jboss.weld.servlet.ConversationContextActivator.sessionCreated(ConversationContextActivator.java:190)
at [internal classes]
As requested, the server.xml - which is generated by Bluemix on deployment.
<server>
<featureManager>
<feature>jaxrs-2.0</feature>
<feature>jsonp-1.0</feature>
<feature>couchdb-1.0</feature>
<feature>ejb-3.2</feature>
<feature>cdi-1.2</feature>
<feature>icap:managementConnector-1.0</feature>
<feature>appstate-1.0</feature>
<feature>cloudAutowiring-1.0</feature>
<feature>eXtremeScale.webapp-1.1</feature>
</featureManager>
<application name='myapp' location='myapp.war' type='war' context-root='some-app'>
<classloader commonLibraryRef='cloudantNoSQLDB-library'/>
</application>
<cdi12 enableImplicitBeanArchives='false'/>
<httpEndpoint id='defaultHttpEndpoint' host='*' httpPort='${port}'/>
<webContainer trustHostHeaderPort='true' extractHostHeaderPort='true'/>
<include location='runtime-vars.xml'/>
<logging logDirectory='${application.log.dir}' consoleLogLevel='INFO'/>
<httpDispatcher enableWelcomePage='false'/>
<applicationMonitor dropinsEnabled='false' updateTrigger='mbean'/>
<config updateTrigger='mbean'/>
<appstate appName='myapp' markerPath='${home}/../.liberty.state'/>
<couchdb id='cloudantNoSQLDB-ith-auth-db' jndiName='couchdb/ith-auth-db' libraryRef='cloudantNoSQLDB-library' username='${cloud.services.ith-auth-db.connection.username}' password='${cloud.services.ith-auth-db.connection.password}' url='${cloud.services.ith-auth-db.connection.url}' enableSSL='true' host='${cloud.services.ith-auth-db.connection.host}' port='${cloud.services.ith-auth-db.connection.port}'/>
<library id='cloudantNoSQLDB-library'>
<fileset id='cloudantNoSQLDB-fileset' dir='${server.config.dir}/lib' includes='commons-codec-1.6.jar commons-io-2.0.1.jar commons-logging-1.1.3.jar httpclient-4.3.6.jar httpclient-cache-4.3.6.jar httpcore-4.3.3.jar jackson-annotations-2.2.2.jar jackson-core-2.2.2.jar jackson-databind-2.2.2.jar jcl-over-slf4j-1.6.6.jar org.ektorp-1.4.2.jar slf4j-api-1.6.6.jar slf4j-jdk14-1.6.6.jar'/>
</library>
<xsWebApp id='session-cache' objectGridName='${cloud.services.session-cache.connection.gridName}' catalogHostPort='${cloud.services.session-cache.connection.catalogEndPoint}' credentialGeneratorClass='com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredentialGenerator' credentialGeneratorProps='${cloud.services.session-cache.connection.username} ${cloud.services.session-cache.connection.password}' objectGridType='REMOTE' securityEnabled='true'/>
So I guess something goes wrong with injecting the HttpRequest... how can I solve this?

content-length header in response not present despite commenting transfer-encoding in axis2.xml

I have an axis2 service running on TOMCAT 6.0.18 with axis2 1.3 version.
I disabled chunking by commenting the transfer-encoding element and changed the HTTP to 1.0
as shown below:
<transportSender name="http"
class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
<parameter name="PROTOCOL">HTTP/1.0</parameter>
<!-- <parameter name="Transfer-Encoding">chunked</parameter> -->
I also implemented LifeCycle interface in the service implementation class.
Here is the init() method code:
public void init(ServiceContext arg0) throws AxisFault {
// TODO Auto-generated method stub
arg0.getConfigurationContext().setProperty(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED,Boolean.FALSE);
arg0.getConfigurationContext().setProperty(HTTPConstants.HTTP_PROTOCOL_VERSION, HTTPConstants.HEADER_PROTOCOL_10);
MessageContext responseMessageContext =
MessageContext.getCurrentMessageContext().getOperationContext().getMessageContext(
WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
responseMessageContext.setProperty(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED,Boolean.FALSE);
responseMessageContext.setProperty(HTTPConstants.HTTP_PROTOCOL_VERSION, HTTPConstants.HEADER_PROTOCOL_10);
Despite having these changes, I still don't see the content-length in the HTTP response header when I called the service. Any ideas?