Hi,
I have a use case where I am fetching requests from a CSV file and calling a secured endpoint using SSL certificates. The requests are grouped by the type of client. For each client simulation, the key store is different. In Gatling, we can do one time configuration or use SSL certificates per user, but how can I switch certificates based on the data in the session? Gatling stores the SSL certificate in a session key attribute - gatling.http.ssl.sslContexts and object of io.gatling.http.util.SslContexts
I am just looking for specific input here on how I can create a new object of SslContexts and overwrite above attribute when I want to switch the SSL Keystore?
Hi,
Thanks for the reply. I am studying this example. I guess it should work in my scenario where I have only one VU and lets say thousand requests. Out of them 500 requests need one certificate and 500 need other based on some field in the data. it does not not matter what field it is - user id or other session attribute. Right?
Inject data into your virtual users from an external source, eg a CSV file
So, yes, when you call feed, gatling put the corresponding data into the Session.
With that knowledge, your global map will contain the association between userId and column3 value (client1 or client2).
The lambda you will give to perUserKeyManagerFactory will be able to make the mapping from the userId through the global map to your column3 value in order to finally give the right keystore.
Ahh, ok. I think I understand now. I keep updating the key manager factory for the user based on the data and it should pick that one for current request. let me try it. Thanks
In code below where I am initializing per user key manager factory the map is not initialized yet and null is passed to the getKeyManagerFactory() method. I guess it is called when initializing not when each request is getting executed. Am I doing something wrong here? I have only one VU
Okay… I was wrong during the whole time! As I said it’s the first time I see such a use case.
Gatling’s creator (Hello @slandelle ^^) only gave access to the userId because KeyManagerFactory is initialized during Virtual User creation so before the first step. Indeed, as a real user, you configure your browser only once and navigate after. As gatling simulate the browser behavior, it will reuse opened connection for a user.
So, I need more context for your use case.
In your csv sample above:
You have only 2 clients, is it only for sample sake or is it a realistic case?
In case of small amount of keystore to manage, I think you should configure the protocol at the scenario level.
Something like:
ScenarioBuilder createScenario(String name, FeederBuilder<String> feeder) {
return scenarion(name)
.feed(feeder)
.exec(/// your scenario)
}
{
setUp(
createScenario("Scenario for client1", csv("forClient1.csv"))
.injectOpen(constantUser(1))
.protocol(createProtocol("client1")),
createScenario("Scenario for client2", csv("forClient2.csv"))
.injectOpen(constantUser(1))
.protocol(createProtocol("client2")),
)
}
Otherwise, we will have to dig deeper in the rabbit hole…
The KeyManagerFactory is instanciated once at the begin of the life of the Virtual User. But the key is asked only when needed.
So, the global map trick may still be of use. But not during the instanciation of the KeyManager, but during the call of its methods.
You will have to create a KeyManagerFactory that will generate KeyManager that will hold the userId
And during the KeyManager life, it will base its answers from the global map.
I’m not sure I am very clear… but it’s quite an unusual topic. (I like that)
Is it possible to better understand your use case?
My understanding is that you have different types of users, each with a different type of keystore.
With Gatling, you can’t have a given virtual user pick a different keystore at runetime depending on the request. The single keystore is created once for each virtual user when it gets started.
As a result, you cannot mix requests requiring different keystores for a given virtual user.
If you want multiple keystores, you must have distinct virtual users.
In short, you need to sort your requests so you have virtual users that only simulate a given type of client.
We have exposed an API which is called by multiple clients/orgs/subscribers/partners whatever you want to call. If we have 10 partners, each one have different key store. I am building a solution where I collect all the requests of all the partners in DB and generate a load from that. I cannot just retrieve the request and send it as the request can belong to different client(of course I will group them as I showed in example) using different key store(I have common trust store). Possible solutions are
Run multiple instances from different machines. Each machine configured for one type of client and keystore(Simplest solution)
On one machine switch the keystore at runtime when a request belong to different client(most flexible)
This one if possible may be a solution which is not bad. Configure 2-3 scenarios with different protocol configuration for 2-3 organizations/clients reducing the instances I have to run.
I tried with 3 option, using per user key manager factory and it seems to be working. Thanks a lot.
It will be great if flexibility is provided at the level of each request though I know it will be inefficient but one can optimize by sorting the records.