Java Tutorial: JNDI Trail Tips for OpenLDAP

With every major release of JDK I quickly review Oracle’s Java Tutorial for any updates. I did that for JDK 8 and will do that for JDK 9 soon. Usually I skip trails like JNDI or JavaFX because I don’t use them at my job. But few months ago I decided to read JNDI trail and want to share some tips I had to use.

Server Setup

So you will need an LDAP server and tutorial refers reader to few vendors. I try to use implementations for Linux and sure there is one – OpenLDAP. Given that my desktop is Windows I have to run it in virtual machine. And for that I use VritualBox + Vagrant. Here is my Vagrantfile (configuration for Vagrant):

Vagrant.configure("2") do |config| 
  config.vm.box = "ubuntu/trusty64" 
  config.vm.network "forwarded_port", guest: 389, host: 1389
  config.vm.provision "shell", inline: <<-SHELL 
    export DEBIAN_FRONTEND=noninteractive 
    apt-get update 
    apt-get install -y slapd ldap-utils gnutls-bin ssl-cert
  SHELL 
end

It deploys Ubuntu an installs all necessary tools. After VM is up and running, you need to login (vagrant ssh) and re-configure slapd for tutorial needs. This official guide helped me a lot.

So first thing is to re-configure OpenLDAP:

sudo dpkg-reconfigure slapd

It will ask for domain name. Use something easy, like example.com. Then it will ask for Organization Name. Enter “JNDITutorial”. Then it will ask for administrator password. Don’t forget it πŸ™‚ For any further questions you can safely use default values.

Next step is to update LDAP with schemas used by tutorial:

sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/java.ldif
sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/corba.ldif

Next thing is populating DB with test data. JNDI trail has a link to tutorial.ldif. You need to download and update its DN names to our installed server: if we used example.com as domain name, then our full DN will be o=JNDITutorial,dc=example,dc=com and we have to ensure that in the file:

sed -i 's/o=JNDITutorial/o=JNDITutorial,dc=example,dc=com/' tutorial.ldif

Now you can upload test data (this is where you need to use admin password):

ldapadd -x -D cn=admin,dc=example,dc=com -W -f tutorial.ldif

There is a big chance you will get something like this:

ldap_add: Object class violation (65)
 additional info: invalid structural object class chain (alias/organizationalUnit)

Ignore that – it doesn’t affect tutorial.

Connection and Authentication

The connection string in JNDI examples must be slightly modified – you have to specify full DN and correct port. Given our configuration and domain example.com env initialization should look like this:

Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:1389/o=JNDITutorial,dc=example,dc=com");

Examples where something is updated or created require authentication. By default OpenLDAP excepts simple authentication. In this case you have to add additional settings to env:

env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=com");
env.put(Context.SECURITY_CREDENTIALS, "password");

Digest-MD5

Example with Digest-MD5 will not work w/o additional modifications. This is what I did to make it functional (thanks StackOverflow). First of all sasldb must be accessible by slapd:

sudo adduser openldap sasl

Then OpenLDAP hast to be configured to use sasldb directly. Create sasldb.ldif file:

dn: cn=config
changetype: modify
replace: olcSaslAuxprops
olcSaslAuxprops: sasldb

And update OpenLDAP configuration with it:

sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f sasldb.ldif

Last thing is to create user in SASLDB. For example user “test”:

sudo saslpasswd2 -c test

That’s it! Now you will be able to connect to OpenLDAP using these environment configuration:

Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, 
  "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, 
  "ldap://localhost:1389/o=JNDITutorial,dc=example,dc=com");
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, "test");
env.put(Context.SECURITY_CREDENTIALS, "*****");

SSL and Custom Sockets

OpenLDAP does not support SSL/LDAPS out of the box. Instead server guide instructs you how to configure TLS which allows to negotiate encrypted connection using the same server port. Though TLS case is slightly different then just SSL protocol – it requires to use JSSE extension. There is a detail trail here. In short: environment settings are the same as for unencrypted connection, but all your work has to be done inside encrypted TLS session:

StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(
  new StartTlsRequest());
tls.negotiate();
// Do your work with LDAP context
tls.close();

The important step to make that work is adding server certificate to JRE keystore. Otherwise your connection will fail. So if you followed OpenLDAP guide then copy /etc/ssl/certs/ldap01_slapd_cert.pem to your local machine (or /vagrant for Vagrant). And then use keytool to import it:

keytool -importcert -alias jnditutorial ^
-file ldap01_slapd_cert.pem ^
-keystore "C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts"

Although this is a Windows example, Linux or Unix would be very similar. Note that keystore is called cacerts (not jseecacerts). Also note a little caveat: if you have both JDK and JRE installed there is a big chance calling “java” runs JRE’s JVM, not JDK’s one.

CMake and MinGW

I used to build my C/C++ toy projects in Code::Blocks, but now I have moved to CLion. And that IDE uses CMake under the hood. It automates all processes (same as Code::Blocks btw), but I was interested how to build my project w/o IDE. CMake has a nice and short tutorial, but it was missing the main point: how to start the build!!! I had to surf Internet for other tutorials for that. One of them gave me some clues. But if you follow it then you may have some interesting troubles. First of all, never run cmake in the source folder! Create a separate folder like “build” and run cmake there. Secondly, if you have MS Visual C++ compiler then cmake will detect it and use it. That wasn’t my goal. So I had to read another tutorial which gave more insight. And then I realized I should have just read cmake –help more carefully πŸ™‚

Anyway here is a short note how to run cmake with MinGW:

mkdir build
cd build
cmake -G "MinGW Makefiles" ..
mingw-make

Explanation:

First of all don’t forget to install CMake from official website (or use choco). Secondly add it to user’s PATH variable. Then you can open command line and go to your project source. CMake generates tons of files and that’s why we better run it in another folder.

Note that running cmake for Linux/MacOS is similar: just use -G “Unix Makefiles” and then make!

Chocolatey: package manager for Windows

We’re all used to package managers in Linux distros: Aptitude in Debian, yum in Read Hat, emerge in Gentoo. This list can be continued. I was very surprised when my colleague suggested to install Homebrew on Macbook to get some tools. I did that and I’m happy. Almost all my tools now get installed with brew install.

If I’m stuck with Windows on my home laptop I thought maybe there is a package manager for Windows? Yes! There is! It’s called Chocolatey! Looks like it’s based on Power Shell so the installation process is super easy. Plus reading there guide isΒ  enough to make it work.

As of now I have installed bunch of my tools using choco install: JDK, Groovy, Gradle, Maven and Intellij IDEA! Isn’t that neat?

 

Windows 10 saves my old horse…

4 years ago I got Dell Precision 6400 at my previous job. It’s BIOS is dated 2011. At that time it was a very descent laptop: Intel i7, 8G of RAM, 256Gb SSD disk and 1Gb ATI Radeon 6740M! It came with Windows 7, but I replaced it with Linux Mint (I even had Gentoo for a short time). I liked it and got used to it despite its enormous size and weight. At some point a year ago I realized I need something more mobile and company gave me Lenovo T460 which I replaced with 15″ MacBook Pro eventually.

Few days ago I felt like I have to use separate workstation for my toy projects so I won’t interfere with my work environment and settings. I don’t want to use my gaming desktop and I want some mobility. So I decided to revive my Dell.

You know I had no troubles with Linux Mint, but I like trying something new. I picked Fedora 24 in memories of my first Linux desktop running Red Hat 9 ten years ago. But I didn’t like Gnome3 and GUI was pretty slow. Eclipse was almost unusable with ugly jitters when you scroll your code. Unfortunately the same thing happened with Linux Mint 18 Sarah! While I remembered Cinnamon as a fast window manager Eclipse Neon still was slow. Plus I had troubles with WiFi card! Sure my GPU driver was the real root cause! As I found out AMD stopped supporting drivers for X11 and latest XOrg server can’t use them. So I ended up with built-in open source driver which kinda works, but looks like can’t use all the power of ATI GPU (for instance, glxgears showed only 60 fps). I’ve heard that AMD (and NVidia) are working hard to provide there native version of open source driver (or at least partly opened), but they are targeting only latest GPUs πŸ™

I was disappointed and almost gave up on my old buddy. And then yesterday I decided to try Windows 10. Just for fun. Apparently you can download Windows ISO for free directly from Microsoft site. You don’t need any product keys and you will get fully functional OS (with reminders to activate it). I made a bootable USB stick and installed Windows 10 Home. And you know what? I am impressed how flawlessly it went and how responsive Eclipse Neon is now! I even tried 3dMark tests and Vantage test showed my old horse is very close to gaming laptop for DX10! I’m not going to play games, but looks like I will stay with Windows for now. Until I got something more modern…

At the end is a quick reminder how to make a bootable USB stick in Linux. So basically there are two methods. For Linux distros usually it’s enough to use dd:

dd if=linux.iso of=/dev/<usb_stick_dev> bs=4M

For Windows you have to use fdisk (or parted) for creating NTFS partition first. (Don’t forget to mark it as bootable!) And then copy all files from Windows ISO image to that USB stick partition. And that’s it!