So I was recently tasked with creating automated tests against a site that utilizes two-way authentication.
- Note: This is 2-way SSL authentication (aka Mutual Authentication). Don’t confuse that for Two Factor Authentication (2FA).
Now, there may be several questions about the task in regards to its validity/merit/requirements/etc, but that’s outside the scope of this article. For the sake of this discussion, let’s simply say that presenting a client-side certificate to the server is the only option.
The unfortunate news is that, as of early 2017, Selenium support for 2-way SSL is non-existent. The issue is that the prompt presented for selecting a client certificate is an OS-level security dialog outside the purview of the browser. Selenium can’t see it, so it can’t do anything about it.
Even without the browser support snag, the auto-select profile approach is further complicated if you’re testing against multiple certificates. No auto selection possible then.
So, what is needed is:
- An isolated Chrome browser
- Reproducible browser configuration
- A means of providing the personal certificate configuraiton for the browser
- The target certificate(s)
- A means of switching certificates
So, knowing that testing against Chrome was desired, and that target test environments could have multiple certificates, I set out for a solution. I needed to solve the browser problem before I could do anything about handing off certs.
Here be dragons.
Not sure if this speaks more to the laziness of programmers, or my own nature, but my first instinct was dodge. Of course, a quick chat with the team confirmed what I suspected – dodging (via some sort of unspecified test-specific entry point) left a core component untested and presented a security risk.
Some StackOverflow posts mentioned using AutoIt, a Windows automation tool, for selecting the prompt.
We explored this, but quickly discovered a pain point: You have no control over the order of certificates in Window’s cert store.
So, what works on one machine may or may not work on another. The antithesis of automated testing.
Around the same time, I discovered a Chromium setting to allow one to auto select a certificate. Great!
Except, the current implementation doesn’t allow you to filter on subject. Unfortunately, I was pulled away to another task shortly after finding this feature.
When I came back to the task, I went searching to refresh a little, and found a StackOverflow post. I was initially excited…until I realized it was the post I had created a month prior to ask if filtering on subject it was possible. And it had no answers.
Though I didn’t tap in to Reddit or Quora (among others), I figured after a month of inactivity that it was time to move on.
The Way Forward
Around the same time I started looking for a new approach, someone pointed me toward Docker as a possible option. I searched GitHub and ran into a library called Zalenium, which looked like it would fit my needs well. Per the author:
This is a Selenium Grid extension to scale your local grid dynamically with docker containers. It uses docker-selenium to run your tests in Firefox and Chrome locally
For those interested in more info, as luck would have it, there was an insanely timely post that went up on TestAutomationGuru discussing the library the same day I went searching. (Side note: I learned after the fact that the library’s author presented about 2 months prior at the Selenium Conference 2017 in Austin, which may have contributed to the influx of info I started seeing)
The library itself is pretty impressive, and got me 90% of the way to my goal. Straight out of the box I was running an isolated browser with reproducible configuration, no conflicts with my desktop environment, and several features helpful for debugging support. Not bad for a single
My work started where the cert support picked up. But, as the adage goes, that last 10% took 90% of the effort.
Next time, I’ll be touching on what the final 10% entailed (spoiler: PRs are your friend, and certs are weird), covering the features used for debugging, and sharing some references concerning two way auth in Linux. Until next time!