I am using gatling for stress testing a web app that uses NTLM authentication. When i recorded the scripts I got a NTLM authentication in the header something like the following
I ran the same test script after few hours and got 401 error. I believe NTLM authentication expired. Is there a way I can handle this in gatling?
or
Is there a way I can generate this authentication and replace it in the test scripts?
Yes, there should be a way, as underlying AsyncHttpClient is supposed to support NTLM.
Honestly, I personally never had a chance to get my hands on such an application and test it.
In your HttpProtocol, you can pass a com.ning.http.client.Realm to the authRealm.
You can build a Realm from a RealmBuilder.
I can try and help you debug this, but you’d have to dig too.
Typical problem for open source projects with Microsoft enterprise only protocols.
Would I be able to work on such a system, I’m pretty confident I could have it running in a matter of minutes-hours, but until then…
I was able to get to past NTLM using following HttpClient class but can’t figure out how to get the authorization header with ntlm token/String out of it. Since gatling does get info out when using recorder, can you point me into some direction as to what can be done.
Here is the code I used:
DefaultHttpClient httpclient = new DefaultHttpClient();
List authpref = new ArrayList();
authpref.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref);
NTCredentials creds = new NTCredentials(“userid”, “Password”, “”, “corp”);
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
Ok Stephane. So I did some digging and came up with the following code. Current problem is I don’t know how to pass the realm back into the httpProtocol. When I append it to httpProtocol variable, I get the following compiler error “value realm is not a member of io.gatling.http.config.HttpProtocolBuilder”
Here is the code:
val builder = new AsyncHttpClientConfig.Builder();
val realm = new Realm.RealmBuilder().setUsePreemptiveAuth(true)
.setPrincipal(“gognaab”)
.setPassword(“password”)
.setNtlmDomain(“corp”)
.setNtlmHost(“http://work.org”)
.setScheme(AuthScheme.NTLM).build()
val realm = new Realm.RealmBuilder().setUsePreemptiveAuth(true)
.setPrincipal(“gognaab”)
.setPassword(“password”)
.setNtlmDomain(“corp”)
.setNtlmHost(“http://work.org”)
.setScheme(AuthScheme.NTLM).build
val httpProtocol = http
.baseURL(“https://esp.qa.finra.org”)
.inferHtmlResources()
.acceptHeader("""/""")
.acceptEncodingHeader(""“gzip, deflate”"")
.acceptLanguageHeader(""“en-US,en;q=0.5"”")
.connection(""“keep-alive”"")
.userAgentHeader(""“Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0"”")
.authRealm(realm)
Also:
don’t set the authorizationHeader, it will be generated by the Realm
don’t try to build an AHC config, Gatling will build one underneath.
So I compiled AsyncHttp client code separately to try to pinpoint the issue. It looks like Netty jar creates the problem. As soon as I remove it, I get Response code 200. Is there a workaround to this?
Here is the code
def main(args:Array[String])
{
val builder = new AsyncHttpClientConfig.Builder();
val realm = new Realm.RealmBuilder()
.setPrincipal(“xxx”)
.setPassword(“xxx”)//put password here
.setUsePreemptiveAuth(true)
.setScheme(AuthScheme.NTLM)
.build();
builder.setRealm(realm).build()
val client = new AsyncHttpClient(builder.build())
println(“before response”)
val response = client.prepareGet(“yyy”)
.execute().get();
Another update. Looks like Netty 4.0.23 jar works fine with standalone code but execution breaks Gatling since there are some dependencies( I got logger error, don’t of any other). If we just copy over those dependencies to netty 4.jar, we should be all set.
the Type1 NTLM Authentication header is still there when sending the Type3 header
preemptive NTLM handshake should only happen when connecting, not for every request
Then, I’m very surprised that you got something running without setting the NTLM domain and host.
Are you sure you got the expected page, even though you got a 200 status?
Actually, my second point was invalid.
The first one was, and I fixed it (but you weren’t impacted as you didn’t make it this far).
You can upgrade your AsyncHttpClient source code, but make sure you build the 1.9.x branch, not master!
Then, IMHO, the first thing to fix is on YOUR side: NTLM domain and host (I think it’s the workstation) are/should be mandatory.
val realm = new Realm.RealmBuilder()
.setPrincipal(“xxx”)
.setPassword(“xxx”)//put password here
.setUsePreemptiveAuth(true)
.setScheme(AuthScheme.NTLM)
.setNtlmDomain(“YOUR_NTLM_DOMAIN_HERE”)
.setNtlmHost(“YOUR_NTLM_HOST_HERE”)
.build();
I downloaded and compiled asyncHttp client from https://github.com/AsyncHttpClient/async-http-client/tree/1.9.x (branch). It still has the same problem (double authentication). As soon as I remove netty jar it works fine. Also, I added back ntlmDomain and ntlmHost in realm builder and I got response body back with 200.
So far I have only seen logger error during gatling run with netty 4. I will try to compile netty4 with netty 3 logging to see if it works.