Working with SSL - Mutual Authentication turned on

Hi,

Can you help me with details or documentation implementing https (2 way Authentication using Certs).

Scenario:

  1. I have APP1 (developed on Scala)
  2. I have written a Functional Test Framework, which test the functionalities of APP1.
  3. When APP1 is configured with one way SSL (https), my application is working fine with https endpoints.

4, But now, two way Authentication is turned on on the server. Seems I am going wrong some where. Can you help me with some steps of SSL Configuration and Certificate installation on my local dev so that I can hit the other Server (APP1) using https.

What I did:

I copied the certificate on my local box. Able to hit the server using Curl command with the certificates.
But failing to hit the server from the application. So I wanted to try as follows:

  1. Import certificates to a keystore
  2. Setup the scenarios, with httpConfiguration where DefaultHttpClient will use keystore, where I can pick the appropriate certificate based on the type of call that I am trying to make.

I am done with keystore creation using keyTool. But how to use this keystore in Scala.

Thanks,
Hanumesh

Just to add,

APP1 using Scala 2.9.3 and I am using Gatling 1.4.6.

I have added the following lines in Galting.conf:

ssl {
trustStore {
#type = “”
#file = “”
#password = “”
#algorithm = “”
}
keyStore {
#type = “”
#file = “”
#password = “”
#algorithm = “”
}
}
Thanks,

Hanumesh

By default, Gatling uses a loose SslContext.
You can indeed provide a real keyStore/trustStore through the gatling.conf file: juste uncomment the fields (remove #) and fill in the values. type is probably JKS (I realize we should support the default value here), file is the file location.
Since 1.5.0, you can also set up those values per user: https://github.com/excilys/gatling/issues/1121

Hope it helps,

Stéphane

Hi Stephane,

I have enabled ssl parameters as follows:

ssl {
trustStore {
type = “”
file = “”
password = “”
algorithm = “”
}
keyStore {
#type = “JKS”
#file = “C:\jdk1.6.0_43\jre\lib\security\myCert1
#password = “xyz”
#algorithm = “”
}
}

But there is no change in the behaviour. All the tests are failing with msg: “Check ‘is’ failed, found 400 but expected 200”

OR

Is there a way that I can associate the keystore with com.excilys.ebi.gatling.http.config.HttpProtocolConfigurationBuilder?

As there are different scenarios, where each scenario needs a different Certificate.

Steps I followed:

Imported the certificates into the java Keystore:
keytool -import -keystore myCert1 -trustcacerts -file CERT1.pem
keytool -import -keystore myCert2 -trustcacerts -file CERT2.pem

Then enables SSL configuration in Gatling.conf (as indicated above)

Please guide me to resolve the issue.

Thanks,

Hanumesh

Why do you still have those #? They are for commenting the properties, you have to remove them so that your configuration can override the default values.

Ooh… its just by mistake, I have uncommented them.

ssl {
trustStore {
type = “”
file = “”
password = “”
algorithm = “”
}
keyStore {
type = “JKS”
file = “C:\jdk1.6.0_43\jre\lib\security\encLIVcert”
password = “abc123”
algorithm = “”
}
}

Are you sure you had to escape the \ the way you did? Do you get an exception somewhere?

Hi Stephane,

Thank you for your remark. Its true. Here is the right configuration:

ssl {
trustStore {
type = “JKS”
file = “C:/jdk1.6.0_43/jre/lib/security/KeyStore1”
password = “abc123”
algorithm = “”
}
keyStore {
type = “JKS”
file = “C:/jdk1.6.0_43/jre/lib/security/KeyStore1”
password = “abc123”
algorithm = “”
}
}

But this is just a 20% of my problem is solved and able to execute atleast a single scenario of my tests.

I have multiple scenarios (for simplicity say 2 scenarios).
Where scenario1 requires certificate1 but for scenario 2 requires certificate 2.

I have imported both the certificates into a single store. In this case, whatever be the first certificate I imported first, only that scenario will be passed and the other scenario fails. Which means, always it try’s to pick the first certificate.
Other option is creating 2 keystores, and associating the appropriate keystore to the scenario. Which cannot be achieved with the version of Galting I am using(Gatling_xxx_1.4.5). But in the post gatling 1.5.0 should solve requirement. Just wanted to confirm, if gatling 1.5.0 is compatilbe with Scala 2.9.3? As my application which I am testing is on Scala 2.9.3.

Thanks for help.
Hanumesh

I thought of testing with Gatling 1.5.2 and installed Gatling 1.5.2 and modified build.scala and updated gatling version to 1.5.2. But I have issues with compilation now as follows:

[error] C:\MyProject\src\main\scala\tests\loadtest\TestAbc.scala:375: value simulation is not a member of com.excilys.ebi.gatling.core.config.GatlingConfiguration
[error] val body = response.getResponseBody(configuration.simulation.encoding)
[error] ^

Here is the code, where I am using custom validation, which worked fine with gatling 1.4.6.

scnAAA = scenario(“Scenario AAA”).
repeat(10) {
feed(csvFeederL).

exec(
http(“Doing step AAA”).
get(“serviceX/funA”).
headers(sendHeadersServiceX).
queryParam(p1, “${p1}”).
queryParam(p2, currentTimeStr).
queryParam(p3, “T1S”).

check(new CheckStatus("${p1}")).

//check(status.is(200)).

check (new MyValidations("${requiredKeysLen}")))

class CheckStatus(pid: EvaluatableString) extends HttpCheck(contentId, ChkStatus.matcher, None, CompletePageReceived)

object ChkStatus {
val matcher = new Matcher[ExtendedResponse, String] {

def apply(feedValue: Session => String, session: Session, response: ExtendedResponse) = {

var pid = feedValue(session)

println("pid: XXXXXXXXXXXXXXXXXXXXXX " + pid)

val body = response.getResponseBody(configuration.simulation.encoding)
if (body != null) {
println("XXXXXXXXXXX: body not null - success "+ body)
Success(Some(“Encoding check passed!”))
} else {
printLogFile("No response. Operation failed for pid: " + pid)
println("No response. Operation failed for pid: : " + pid)

Failure("check failed (Not 200) for pid: " + pid)
}

}
}
}

Please help me with the changes to fix the above compilation error.

Thanks,
Hanumesh

Hi,

  • First certificate of the store being picked up: that could probably be made configurable, please open an issue in the Async Http Client bug tracker
  • Gatling 1.5 compiles with Scala 2.9.3, the move to 2.10 was only made in Gatling 2
  • Migrating issues: we have a migration guide in the wiki: https://github.com/excilys/gatling/wiki/Migrating
    Cheers,

Stéphane

Hi Stephane,

I switched the approach and used custom protocol instead. Now I am able to specifiy the keystore to be used for the scenario and it works fine.

But I have some other challenges now.

Context: I need to fire a request with 3 parameters where values for those parameters will be supplied from a csv file (data file).

Problem: Feeder is not working properly and I observed always the first value in the feeder is sent in every iteration. Could you guide me with this problem please. Here is my scenario.

val csvFeeder = csv(“mycsv.csv”).circular

val scenarioForVod = scenario(“MyScenario with https”).
repeat(myList.length) { // Count of mylist and rows in csv file are same
feed(csvFeeder).
exec(myProtocol(“Encode VOD content”).
// schema: String, userInfo:String, urlhost:String, port:Int, action:String, requestParams:String, keystore:String, pwd:String
getX(“https”, null, “hostnamehere”, portNo, “/abc/getVal”, “param1=”+csvFeeder.next.apply(“myID”) +"&param2=1001&param3=2001", “KeyStore1”, “KeystorePass”)) // In csv, I have 2 values in each row given to param1 and param2

}

In the above code, I need to iterate the csv file and each iteration, it needs to replace a value of each row of csv in the request. But here, always for every request submitted, the value is the same and it is the first rows value only. (I need to pass different values (from different rows) for each request)

I guess, this works fine with default http protocol( and “${myId}”). But the same not working with userdefined protocol? Is there any other way?

Initially I tried with “${myID}”, but same value instead of replacing with actual value, same value is being sent (${myID}.
Then I tried csvFeeder.next.apply(“contentKeyId”). This time its replaced with value of CSV under the column contentKeyId, but not advancing to next row in futher iterations. Instead, only first row value is getting passed to the request.

Thanks,
Hanumesh

Your getX is only evaluated once, when the Simulation instance is created, so is csvFeeder.next.apply(“myID”).
In http protocol, get actually takes a function parameter (Session => String in Gatling 1, Session => Validation[String] in Gatling 2) and this function is evaluated on every request.
There’s an implicit in scope that automatically converts String into functions when required (when you try to pass a String an the method actually takes a function).

Cheers,

Stéphane

Actually I solved the problem long back, just thought of updating so as others can know about it.

Pass the csvFeeder itself to the getX() method, then within it, able to get the next value.

Thanks,
Hanumesh