Tuesday 27 November 2012

UNIX File Permissions for Java 7's java.nio.file Package

During a recent project at work, I found myself needing the ability to work with UNIX specific file permissions with Java 7's java.nio.file package, but unfortunately it's not trivial to do so. The package currently provides functionality to get and set POSIX file permissions, but these file permissions do not include certain permissions such as setting the GID or UID bit.

Because it wasn't trivial to work with UNIX specific file permissions, I've created a quick project to do just that. The project includes a UnixFiles class, which attempts to mimic as closely as possible the current functionality of getting and setting POSIX file permissions. There is also functionality to check whether a supplied FileSystem supports UNIX file permissions, and methods to easily move backwards and forwards between UNIX and POSIX file permissions to try and aid with writing code that can run on any OS (well, one which at least supports POSIX file permissions).

Okay, quick code example to show how to use it:

Path path = Paths.get("/home/adam/test.txt");
Set<UnixFilePermission> perms = 
        UnixFilePermissions.parseMode("777", 8);
if (UnixFiles.hasUnixFilePermissions(path.getFileSystem())) {
    UnixFiles.setUnixFilePermissions(path, perms);
}
else {
    Files.setPosixFilePermissions(
                            path, 
                            UnixFilePermissions.toPosix(perms));
}

As you can see, I've added functionality to move between a "mode" and the set of file permissions. In the example, I used the octal permissions 777, which are -rwxrwxrwx. If we were to print out the set of file permissions returned from the parseMode method, we would see the following:

OWNER_READ
OWNER_WRITE
OWNER_EXECUTE
GROUP_READ
GROUP_WRITE
GROUP_EXECUTE
OTHERS_READ
OTHERS_WRITE
OTHERS_EXECUTE

So, you can get this project from my github. All feedback, pull requests, bug reports, etc, are welcome.

Saturday 6 October 2012

OpenLDAP: Part 1 - Server Installation

Introduction


I've recently had the (dis)pleasure of attempting to install an OpenLDAP server at work for centralised authentication and policy control. The major problem that I've experienced during this process is that the majority of the documentation and tutorials available, including OpenLDAP's website and wiki, focus on the older slapd.conf method of configuration, rather than configuration via the dynamic configuration engine introduced in OpenLDAP 2.3.

Now that I have my OpenLDAP 2.4 server up and running, with mirror mode replication, TLS and password policies, I feel it is about time to commit to writing the process involved in setting up the server, configuring replication, TLS and password policies, and setting up the clients.

This will be a three part tutorial, with this first part detailing installation of the server.

I'm running Centos 6.2, but this tutorial should be suitable for all RHEL derived distributions, and I imagine that the step-by-step instructions can easily be tweaked to work with nearly all Linux distributions.

Installation


Firstly, we need to actually install the correct packages on the server:

sudo yum -y install openldap openldap-clients openldap-devel openldap-servers

Configuration


Move to the openldap directory:

cd /etc/openldap/

Now we're going to want to make quite a few changes to the configuration files. Firstly, open the database configuration file in vi:

vi slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif

...and you should see a file that looks as follows:

dn: olcDatabase={0}config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to *  by * none
olcAddContentAcl: TRUE
olcLastMod: TRUE
olcMaxDerefDepth: 15
olcReadOnly: FALSE
olcRootDN: cn=admin,cn=config
olcSyncUseSubentry: FALSE
olcMonitoring: FALSE
structuralObjectClass: olcDatabaseConfig
entryUUID: 82f0764c-bb56-1030-8724-e591e38e1c30
creatorsName: cn=config
createTimestamp: 20111215105139Z
entryCSN: 20111215105139.539186Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20111215105139Z

We want to modify the line that begins with olcRootDN to change it to our network's DN. This will look as follows:

olcRootDN: cn=Manager,dc=adambh,dc=co,dc=uk

The dc elements make up the domain name (in this case, adambh.co.uk), and the cn element is the Common Name of the manager of this DN.

Save and close the file, then open the HDB specific file in vi:

vi slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif

...and you'll see a file that looks as follows:


dn: olcDatabase={2}hdb
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
structuralObjectClass: olcHdbConfig
entryUUID: c9f8199e-a41e-1031-836a-1bd144c7fb02
creatorsName: cn=config
createTimestamp: 20121006162947Z
entryCSN: 20121006162947.827617Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20121006162947Z


Here, we need to modifiy the lines starting with olcSuffix and olcRootDN to the following:

olcSuffix: dc=adambh,dc=co,dc=uk
olcRootDN: cn=Manager,dc=adambh,dc=co,dc=uk

...then save and close the file.

Open the monitor configuration file in vi:

vi slapd.d/cn\=config/olcDatabase\=\{1\}monitor.ldif

...and you'll see the following:

dn: olcDatabase={1}monitor
objectClass: olcDatabaseConfig
olcDatabase: {1}monitor
olcAccess: {0}to *  by dn.base="cn=manager,dc=my-domain,dc=com" read  by * none
olcAddContentAcl: FALSE
olcLastMod: TRUE
olcMaxDerefDepth: 15
olcReadOnly: FALSE
olcSyncUseSubentry: FALSE
olcMonitoring: FALSE
structuralObjectClass: olcDatabaseConfig
entryUUID: 82f08e34-bb56-1030-8726-e591e38e1c30
creatorsName: cn=config
createTimestamp: 20111215105139Z
entryCSN: 20111215105139.539186Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20111215105139Z

Here, we need to modifiy the line starting with olcAccess to the following:

olcAccess: {0}to *  by dn.base="cn=Manager,dc=adambh,dc=co,dc=uk" read  by * none

...then, again, save and close the file.

Last thing we need to do here is move a DB_CONFIG example file into the correct directory and rename it from an example to an actual file.

cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG

That's about it for modifying the configuration files. We can test that the configuration is correct by starting the slapd service.

service slapd start

...and that should return:
Starting slapd:       [OK]

The majority of the configuration of the LDAP entries can be done via the LDAP Account Manager website (which will be installed/configured in a later post), however, we need to manually add entries for the organisation and the Manager before LDAP Account Manager can be used. To do this, let's move over to the tmp directory:

cd /tmp

...and we're going to want to create a new file here called setup.ldif:

vi setup.ldif

...which should contain the following:

dn: dc=adambh,dc=co,dc=uk
o: AdamBH, Ltd
objectclass: dcObject
objectclass: organization

dn: cn=Manager,dc=adambh,dc=co,dc=uk
cn: Manager
sn: Manager
objectclass: top
objectclass: person
userPassword: {a password here}

Obviously, put a real password in place of {a password here}, which will be the password used to access the manager account, then save and exit the file.

Now we need to commit this file to the database. Assuming that the slapd service is now currently running, we firstly need to stop it.

service slapd stop

...then we need to commit the file to the LDAP databases:

slapadd -v -l setup.ldif

...which should produce the following output:

added: "dc=adambh,dc=co,dc=uk" (00000001)
added: "cn=Manager,dc=adambh,dc=co,dc=uk" (00000002)
_#################### 100.00% eta   none elapsed            none fast!      
Closing DB...

Exciting stuff. Before restart the slapd service, we need to modify the DB files to be owned by the ldap user, otherwise the slapd service will continually complain about it when being started up.

chown ldap:ldap /var/lib/ldap/*

Then we need to once again start the slapd service.

service slapd start

We can confirm that the changes have taken effect in the database with the following command:

ldapsearch -x -b "dc=adambh,dc=co,dc=uk" -H "ldap://localhost"

...which should product something similar to the following output:

# extended LDIF
#
# LDAPv3
# base <dc=adambh,dc=co,dc=uk> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# adambh.co.uk
dn: dc=adambh,dc=co,dc=uk
o: AdamBH, Ltd
objectClass: dcObject
objectClass: organization
dc: colo2

# Manager, adambh.co.uk
dn: cn=Manager,dc=adambh,dc=co,dc=uk
cn: Manager
sn: Manager
objectClass: top
objectClass: person
userPassword:: aG9tZS5tNDFhMg==

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2
If that worked then, HUZZAH, we have a working LDAP server. The last things to do is modify IPTABLES to allow the LDAP port:

iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 389 -j ACCEPT
service iptables save
service iptables restart

...and then make sure that ldap starts on boot:

chkconfig slapd on

I just hope that this guide has helped to allay some of the frustrations I felt when trying to set this up. In the next few parts, I'll go through setting up the client, installing a WUI for easy management of the LDAP server, and some additional topics such as TLS between the clients and server, replication and password policies.