Wednesday, January 28, 2015

Installing openSSL inside your Perlbrew

A while ago I had to install some monitoring scripts in reasonable old Linux servers. The script would require a substantial number of Perl modules from CPAN and I was not interested in running the issue to convince the administration responsible team (I didn't have root access) to install those modules for me.

The easiest way to solve that was installing Perlbrew. Perlbrew allows anyone to download perl source code, compile and install anywhere, including your own home directory (Perlbrew is available only for UNIX-like operational systems at the moment I'm writing this post).

Since I didn't have direct access to the internet on those servers, what I did was create a VM with the same Linux distribution and version and install Perlbrew from there, connecting to CPAN and installing all dependencies that I need too.

After that I just had to generate a tarball from everything and move to those Linux servers. Another wonder from Perl community made my day.

After some days of having those test scripts working, I had receive a new testing request: validate if some webpages were working fine. Perl has a lot of tools to help with that, so no issue here. The problem is that those webpages where available only through TLS and the version available of openSSL was so old that newer versions of IO::Socket::SSL would simple not compile with it.

Old libs and no play makes Jack a dull boy

IO::Socket::SSL depends on Net::SSLeay, that will then look for shared libraries of openSSL to compile C/XS code.If there are changes in the expected interface, this code will not compile at all.

Some how I would need to avoid using the present openSSL binaries and download and install a newer one inside my Perlbrew setup. I spent an unpleasant time trying to do that (I'm not a C programmer) because first I thought that I should use static libraries, than I tried to force shared libraries... and during all this time I was being stomped by SELinux (yes, it was installed in all those servers).

It turned out at the end that a much more simple was available: just compile openSSL with standard options. And some changes regarding system variables. Let's review my recipe on that:
  1. install Perlbrew: you probably already know how to do that. If not, just visit it's website for instructions.
  2. Install openSSL: no magic here, the simplest
  3. Installing Perl modules that depends on openSSL

Step 2 is pretty easy. I suggest to set up the option --prefix as a sub directory under the Perlbrew install. For instance, that might be something like:

./config shared --prefix=$PERLBREW_ROOT/openssl
make
make test
make install

For Step3, some previous setup is necessary.

Create a test file named "openssl_env" in your $HOME with the following content:

export OPENSSL=$PERLBREW_ROOT/openssl
export C_INCLUDE_PATH=$OPENSSL/include
export LIBRARY_PATH=$OPENSSL/lib
export LD_LIBRARY_PATH=$LIBRARY_PATH:$LD_LIBRARY_PATH
export OPENSSL_PREFIX=$PERLBREW_ROOT/openssl

Now go back to the shell and type:

perl -MCPAN -e shell
get Net::SSLeay
look Net::SSLeay

perl Makefile.PL
make
make test
make install
exit

Make sure all tests from "make test" worked fine. If not, check if the declared variables paths are correct.

Now edit again the openssl_env file and comment the C_INCLUDE_PATH variable. Should be unnecessary to have it setup unless you need to compile more stuff.

Now add the following to the end of your .bashrc (or whatever other shell configuration file you're using):

source $HOME/openssl_env


Now, go back to the CPAN shell to install IO::Socket::SSL:

perl -MCPAN -e shell install IO::Socket::SSL

If you did everything right, now you should have a plenty functional customized Perl with openSSL working!

4 comments:

  1. Thanks for your excellent article!
    But I am having a problem when I run the command:

    perl makefile.PL

    It does not find the newly compiled openssl version (1.0.2d) installed in $PERLBREW_ROOT/openssl.
    Instead, it finds and uses the ORIGINAL operating system openssl:

    *** Found OpenSSL-0.9.8e installed in /usr
    Do you know how to fix this?

    Thanks in advance for your help!

    David.

    ReplyDelete
  2. Found the answer:

    export OPENSSL_PREFIX=$PERLBREW_ROOT/openssl

    and then it found the newly compiled openssl version.

    ReplyDelete
    Replies
    1. You're right David! Something changed between this and newer releases of Net::SSLeay.
      I'll update the post, thank you for sharing the information!

      Delete
  3. Thanks for this. I used the process to install libxml2 and libxslt into my perlbrew as well.

    ReplyDelete