3

I have a project with microservices deployed in Bluemix with Docker containers. All microservices are written in Java and the communication is using JKS files.

I also developed a microservice in Node.js with Express.js. To consume the other microservices, I used the Request module with option.agentOptions feature and a pfx file, like this:

var options = {
        uri: config.get("https://www.example.com/ms/service"),
        method: 'POST',
        body: data,
        json: true,
        headers: {
            'Content-Type': 'application/json; charset=UTF-8'
        },
        agentOptions: {
            pfx: fs.readFileSync(config.get("/path/to/file.pfx")),
            passphrase: config.get("passphraseText"),
            servername: config.get("serverName")
        }
    };

request(options, function (error, response, data) {
     //handing response
});

I tried to use the Solicit crate with default example for HTTPS but it fails with:

4 | use solicit::http::client::tls::TlsConnector;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not find `tls` in `client`

I couldnt find another crate, library or framework for made it, how can I make this requests?


EDIT

Apparently Solicit isn't an alternative for its lack of maintenance so it is no longer an alternative solution to this question, Here's the reason.

Community
  • 1
  • 1
Deoxyseia
  • 1,359
  • 18
  • 29

1 Answers1

5

At the moment, you should prefer the hyper client over solicit. The latter has not been updated since 2015, and hyper is being given better maintenance. Add hyper = "0.10.10", and hyper-native-tls = "0.2.2" to your dependencies. For specifying the client certificate to use, we can leverage the features of native_tls. In particular, TlsConnectorBuilder and Pkcs12 are what you're looking for.

use std::fs::File;
use std::io::Read;
use hyper::client::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use hyper_native_tls::native_tls::{TlsConnector, Pkcs12};

// fetch the PKCS12 client certificate
let cert = {
    let cert_file = File::open("/path/to/cert.pfx")?;
    let mut cert_raw = Vec::new();
    cert_file.read_to_end(&mut cert_raw)?;
    Pkcs12::from_der(&cert_raw, "mypassword")?
};

// specify the TLS connection with the builder pattern 
let tls_conn = TlsConnector::builder()
    .identity(cert)?
    .build()?;
let ssl = NativeTlsClient::from(tls_conn)?;
let https_conn = HttpsConnector::new(ssl);

// proceed as usual
let client = Client::with_connector(https_conn);
let endpoint = "https://www.example.com/ms/service");
let resp = client.get(endpoint).send()?;

In solicit, the documentation states that the tls submodule was only available when the "tls" feature is enabled for this dependency. Nevertheless, this would lead to further dependency conflicts (see Why does solicit 0.4.4 attempt to use openssl 0.9.12 even though I have openssl 0.7.14 in my Cargo.toml?). Sticking to hyper instead of solicit is a much safer choice.

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • Thanks @E_net4, I added that but now the error is: `error: Package openssl 'v0.9.12' does not have these features: 'tlsv1_2, npn'`, also I added `openssl = { version = "0.9.12", features = ["v101", "v102", "v110"] }` but this second error persist. – Deoxyseia May 19 '17 at 01:26
  • @Deoxyseia I have updated the answer with an alternative. – E_net4 May 19 '17 at 09:04
  • I think fixing Solicit isn't the best solution on security topic that is just what I want to do, especially for having to fix openssl to 0.9. About hyper does not solve the original question, how use client certificate for make requests in case the server requires it. [More info](https://security.stackexchange.com/a/20847/116719) – Deoxyseia May 24 '17 at 04:52