This is how I generate my SSL cert, key, etc:
openssl genrsa -out server.key 1024
openssl rsa -in server.key -out new_key.pem
openssl req -new -key server.ke
It seems you are generating self-signed certificates (which is fine), but the operations you are making with the openssl
utility are confusing.
Line 1 is OK, it generates a private key.
Line 2 is useless: the output key is the same as the input key! (Try to diff
the two keys to see).
Line 3 generates a CSR and line 4 actually self-signs it, so they can be merged together in one line as we will see.
Now, let's take a step back and let's try to understand what we are doing :-)
You are using SSL to authenticate and encrypt the communication between a Thrift server and a Thrift client. I assume you want to both:
To make an HTTPS analogy, (1) is the classic server certificate, (2) is normally a username/password for the user. But with Thrift SSL, we will obtain mutual authentication by issuing a certificate also to the client.
The examples I will make will use self-signed certificates. They can easily be adapted to a mini CA managed by openssl, and I leave this as an exercise to the reader.
Generate the server private key:
openssl genrsa -out server-key.pem 2048
Generate the associated public key and self-sign it:
openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000
Generate the client private key:
openssl genrsa -out client-key.pem 2048
Generate the associated public key and self-sign it:
openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000
Note: when openssl req
asks for "Common Name (e.g. server FQDN or YOUR name)"
, put the FQDN of the host on which the Thrift program will run. This will allow not to customize Thrift's AccessManager
class. If on the other hand the FQDN can not be known in advance, one needs to inherit AccessManager
and override the verify()
methods accordingly. See TSSLSocket.cpp
.
Good, now to the code.
On the server side:
socketFactory->server(true);
is redundant, remove it.
socketFactory->authenticate(false)
is a bit misleading. A better name would have been authenticatePeer
. If you say false
, it will not authenticate the client, but we decided before we want mutual authentication.
So, a SSL preamble for a server is:
try {
signal(SIGPIPE, SIG_IGN); // See README.SSL
shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
sslSocketFactory->loadPrivateKey(myKey);
sslSocketFactory->loadCertificate(myCert);
sslSocketFactory->authenticate(true);
sslSocketFactory->loadTrustedCertificates(trustedCerts);
sslSocketFactory->ciphers("HIGH:!DSS:!aNULL@STRENGTH");
...
} catch (TException& tx) {
....
}
Where myKey
is server-key.pem
, myCert
is server-cert.pem
and trustedCerts
is... either the cert of a trusted CA, or, in case of a self-signed cert, the cert of the client. You can cat
multiple certs one after the other in the same file. In our example, we will put client-cert.pem
that we created before.
A SSL preamble for a client is exactly the same, with the correct client private key, client cert and, for trustedCerts
, the cert of the peer: server-cert.pem
that we created before.
That's all :-) Try to understand before jumping to code it, if you don't have a clear picture of how SSL (mutual) authentication works, it is difficult to understand the error messages. The code I showed is tested to work.
Documentation-wise, unfortunately Thrift is close to nothing. For SSL, you can see: lib/cpp/README.SSL
, test/cpp/src/TestServer.cpp
and test/cpp/src/TestClient.cpp
. Be warned that TestServer.cpp
doesn't do mutual authentication, which is an error IMHO.