10

I am using Selenium to test a web site which has HTTP Auth and now even SSL certificate.

As workaround for HTTP Basic Authentification I am using ChromeDriver - http://code.google.com/p/selenium/wiki/ChromeDriver and opening URLs in format

https://username:password@my-test-site.com

But now from security reasons, Client certificate needs to be installed on PC in order to log into that application.

However, ChromeDriver cannot see the "select certificate" prompt and I even cannot switch to it as Alert.

Did somebody solved this issue?

Pavel Janicek
  • 12,577
  • 12
  • 47
  • 76
  • I faced the exact same problem and ended up writing a small proxy to handle the certificates. See https://stackoverflow.com/questions/56017155/add-ssl-certificate-to-selenium-webdrive – Tagas Jun 04 '19 at 08:54

4 Answers4

7

You can tell the Chrome browser to use a specific client certificate for a particual URL by adding a registry KEY with the following content:

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\AutoSelectCertificateForUrls\1 = "{\"pattern\":\"https://www.example.com\",\"filter\":{\"ISSUER\":{\"CN\":\"cn of issuer\"}}}"

You may add additional entries by adding additional keys under the same branch.

It's a little more complex on Linux as you need to modify the preferences which are in json format under the following location:

~/.config/chromium/Default/Preferences

It looks like the above option only works for machines joined to an Active Directory domain. In case the above steps don't work You may try using a preconfigured template to introduce the changes available for download from the following url: https://www.chromium.org/administrators/policy-templates

5

Instead of installing the Client Certificate you could just tell Chrome to ignore the untrusted certificate error using the --ignore-certificate-errors command line switch.

To do this, create your instance of ChromeDriver as follows:

DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability("chrome.switches", Arrays.asList("--ignore-certificate-errors"));
driver = new ChromeDriver(capabilities);
Dave Webb
  • 179,733
  • 56
  • 298
  • 296
  • 2
    Problem is, that the site I am trying to access actually needs client certificate to have installed. And because we have more test environments, each environment needs specific certificate... – Pavel Janicek Sep 23 '11 at 13:59
  • How do I do this from the command line using the standalone selenium server? – B2K Aug 24 '16 at 16:23
  • 1
    @PavelJanicek were you able to solve this problem. How do I mention which cert to choose on chrome driver? – Manvi Feb 05 '18 at 20:10
  • @Manvi I was unable to solve that problem. At the end, we (testers) negotiated a test environment where client certificates were not needed – Pavel Janicek Feb 15 '18 at 12:55
  • @PavelJanicek I was able to solve that issue with phantom driver. I posted solution with details I used. – Manvi Feb 16 '18 at 16:07
  • I am connecting to a [StandaloneChrome](https://github.com/SeleniumHQ/docker-selenium/tree/master/StandaloneChrome) using a Remote driver. Adding `capabilities['acceptInsecureCerts'] =True` (python) solved the `Your connection is not private` browser error in my case. – tshalif May 06 '20 at 04:43
2

I solved this issue with below code

DesiredCapabilities cap = DesiredCapabilities.chrome();
ImmutableMap<String, String> commandLineArguments = ImmutableMap.<String, 
String>builder()
    .put("web-security", "false")
    .put("ssl-protocol", "any")
    .put("ignore-ssl-errors", "true")
    .put("webdriver-loglevel", "DEBUG")
    .put("ssl-client-certificate-file", certificatePath)
    .put("ssl-client-key-passphrase", certificatePassword)
    .build();
String[] params = commandLineArguments.entrySet().stream()
    .map(e -> String.format("--%s=%s", e.getKey(), e.getValue()))
    .collect(Collectors.toList())
    .toArray(new String[0]);
cap.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, params);
cap.setCapability(ChromeOptions.CAPABILITY, options);
WebDriver driver = new PhantomJSDriver(cap);
driver.get(Url);

But I had to convert my pfx certificate to pem using below command

openssl pkcs12 -in client_ssl_cert.pfx -out client_ssl_cert.pem -clcerts
Manvi
  • 1,006
  • 1
  • 11
  • 37
0

To build upon Manvi's answer, I could not get it working using a PEM certificate nor a PFX certificate, so I had to manually extract the certificate and key from my PFX file using openssl

Extract the certificate

openssl pkcs12 -clcerts -nokeys -in "SourceFile.PFX" -out certificate.crt -password pass:"MyPassword" -passin pass:"MyPassword"

Extract the key

openssl pkcs12 -nocerts -in "SourceFile.PFX" -out private.key -password pass:"MyPassword" -passin pass:"MyPassword" -passout pass:TemporaryPassword

Code

File path=new File(phantomJSBinaryFile);
System.setProperty("phantomjs.binary.path",path.getAbsolutePath());

ChromeOptions cap =new ChromeOptions();
ImmutableMap<String, String> commandLineArguments = ImmutableMap.<String, 
String>builder()
    .put("web-security", "false")
    .put("ssl-protocol", "any")
    .put("ignore-ssl-errors", "true")
    .put("webdriver-loglevel", "INFO")
    .put("ssl-client-certificate-file", certificatePath) //certificate.cer
    .put("ssl-client-key-file", keyPath) //private.key
    .put("ssl-client-key-passphrase", pwd)
    .build();

String[] params = commandLineArguments.entrySet().stream()
    .map(e -> String.format("--%s=%s", e.getKey(), e.getValue()))
    .collect(Collectors.toList())
    .toArray(new String[0]);

cap.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, params);
//cap.setCapability(ChromeOptions.CAPABILITY, options);

WebDriver driver = new PhantomJSDriver(cap);
driver.get(url);
System.out.println(driver.getTitle());
fennelon
  • 16
  • 1