I have a need to run Gatling with each user-session do its own client-authenticated TLS handshake and POST to our company’s service. So try with “per virtual user stores” in Gatling’s doc but failed with 401 response.
After one day of trying and failing, I decided to use Apache httpclient to do the same cilent-authenticated TLS behavior and make it successfully.
Below is the httpclient snippet code extracted:
`
@Test
public void client_cert() throws Exception {
String baseUrl = “https://stubaddr.company.service.com”;
KeyStore clientKeyStore = getStore(A_KEYSTORE, DEFAULT_PASS_VALUE);
SSLContext sslContext =
new SSLContextBuilder()
.loadKeyMaterial(clientKeyStore, DEFAULT_PASS_VALUE, (map, socket) → “myalias”)
.build();
httpclient = HttpClients.custom().setSSLContext(sslContext).build();
HttpPost post = new HttpPost(baseUrl + “/set/something”);
post.setHeader(HttpHeaders.CONTENT_TYPE, “application/x-www-form-urlencoded”);
post.setEntity(new StringEntity(“something=1”));
CloseableHttpResponse response = httpclient.execute(post);
assertThat(response.getStatusLine().getStatusCode(), equalTo(204));
}
`
Not having a clue why this code passed but using Gatling failed, so I output the ssl debug log and found something worth checking.
When using Gatling to do this, during the TLS handshake process, when the server asked for "CertificateRequest" to the client, there's a warning message about no suitable certificate found:
Forgot to post my Gatling code…
BTW, I am using Gatling 2.3 and run the script both through maven and Gatling’s bin script. But still got the same 401 result in both ways.
`
package a.company
import io.gatling.core.Predef._
import io.gatling.core.structure.ScenarioBuilder
import io.gatling.http.Predef._
import io.gatling.http.protocol.HttpProtocolBuilder
class TestCert extends Simulation {
val baseConfig: HttpProtocolBuilder = http.disableWarmUp.disableClientSharing
val simulateData: ScenarioBuilder = scenario(“POST_with_cert”)
.exec { session =>
session
.set(“gatling.http.ssl.keyStore.file”, “/home/gatling_cert_test/A_keystore.jks”)
.set(“gatling.http.ssl.keyStore.password”, “changeit”)
}
.exec(
http(“POST data”)
.post(“https://stubaddr.company.service.com/set/something”)
.header(HttpHeaderNames.ContentType, HttpHeaderValues.ApplicationFormUrlEncoded + “; charset=utf-8”)
.body(StringBody(“something=123”))
.check(status.is(204))
)
setUp(
simulateData.inject(atOnceUsers(1))
).protocols(baseConfig)
}
`
We don’t support JKS aliases atm.
Manage to add some customized function to set an alias for per-user-session’s keystore. But that resulted in overriding existed gatling-http jar and adding apachehttp jars.
Although solve my needs but still hoping to see Gatling support this officially.
Although solve my needs but still hoping to see Gatling support this
officially.
Why not contribute a clean implementation then?
*Stéphane Landelle*
*GatlingCorp CEO*
slandelle@gatling.io