Tuesday, 27 January 2015

A pure ruby Attribute Authority client

Even if you can query IdP Attribute Authority with resolvertest, and you can test the tiny details with a curl call, a ruby attribute authority client is handy should you desire, for instance, to bulk load the IdP with many parallel requests.

Moreover, the curl approach is very slow because you need to modify the request xml file to put a timely IssueInstant and a unique RequestID.

You can browse the source at the github project page

Tuesday, 9 September 2014

SASL/DIGEST-MD5 with OpenLDAP-2.4.39

In order to authenticate users with Digest-MD5 the first choice to do is either store passwords in a file (sasldb2) on ldap server or into directory. The olcSaslAuxprops attribute in cn=config defines the path to follow.

Passwords in salsdb2

Start with:
sudo apt-get install sasl2-bin
than create a user:
sudo saslpasswd2 -c francesco
(script prompts for password and confirm password)
sudo chown openldap /etc/sasldb2
Modify cn=config with the following:
dn: cn=config
changetype: modify
replace: olcSaslAuxprops
olcSaslAuxprops: sasldb
create a map for the user:
dn: cn=config
changetype: modify
delete: olcAuthzRegexp
olcAuthzRegexp: "uid=francesco,cn=digest-md5,cn=auth" "cn=joe,dc=example,dc=org"
The entry cn=joe,dc=example,dc=org can be created later, or not created at all, if you simply need a principal to fulfill a ACL rule.
Restart OpenLDAP in order to apply olcAuthzRegexp (required by mine experience on Debian, OpenLDAP-2.4.39).
Test with:
ldapwhoami -U francesco -H ldapi:/// -Y DIGEST-MD5
SASL/DIGEST-MD5 authentication started
Please enter your password: 
SASL username: francesco
SASL SSF: 128
SASL data security layer installed.
dn:cn=joe,dc=example,dc=org
Type the password choosed in the saslpasswd2 step. If by chance you are logged is as 'francesco', the -U francesco switch can be omitted.

Passwords in directory

Create the joe user:
dn: cn=joe,dc=unimore,dc=it
objectClass: inetOrgPerson
cn: joe
sn: user
uid: joe
description: Just plain Joe
userPassword: joesecret
Rollback the olcSaslAuxprops if you changed it (if not, this step is not necessary as it is the default):
dn: cn=config
changetype: modify
replace: olcSaslAuxprops
olcSaslAuxprops: slapd
Add the olcAuthzRegexp rules to map the MD5-DIGEST username to a directory entry, and you are ready:
ldapwhoami -U francesco -H ldapi:/// -Y DIGEST-MD5
then type the joe's password (joesecret in this example).
  • "client response doesn't match what we generated (tried bogus)" means you typed the wrong password.
  • "generic failure: unable to canonify user and get auxprops" could be either userPassword is not CLEARTEXT or userPassword is not readable by joe user (because of ACLs).
You are not going to do much with MD5-DIGEST without reading: OpenLDAP docs about Mapping Authentication Identities

Monday, 8 September 2014

DIGEST-MD5 what is good for?

DIGEST-MD5 sasl auth mech require OpenLDAP to store clear text passwords in the directory.

So you could wonder if it is worth implementing it.

DIGEST-MD5 protects passwords from sniffing even if an attacker could dump the whole network traffic. On the other hand, if network traffic is not ciphered a sniffer could eavesdrop the directory data.

The use case can't be about sensible data because if you plan to store in directory data which is supposed to be read only by authorized people, you are going anyhow to implement SSL or StartTLS. So you have no need to protect passwords on the wire as the traffic on the wire is encrypted.

Odd are good that if you have public data you are not asking authentication (anonymous access is enough). So DIGEST-MD5 is useless either.

What about a directory holding public data (work telephone number, for instance), with anonymous read access but authenticated update by selected people only?

I think this is the great use case for DIGEST-MD5: a directory that can be read by anonymous readers, without SSL nor StartTLS. Authorized users can update directory with plain text data but still userpassword is safe from sniffing.

Friday, 24 January 2014

Ruby spec a ffi-rzmq project

Intro

When working with async messaging, tests are more difficult. ffi-rzmq library is special because messages are received in a weird way:
receiver.recv_string(buffer = "")
The message payload is in the buffer variable, which is passed as a parameter. To achieve testing I had to turn buffer to a instance variable (@buffer) and I resorted to the mock results Arbitrary Handling
    # e is a Emitter instance, my fictionary zeromq-based class
    @endpoint.should_receive(:recv_string) do
      e.instance_variable_set("@buffer", my_data)
    end
    @endpoint.should_receive(:recv_string) do 
      e.instance_variable_set("@buffer", "__END_OF_DATA__")
    end
@endpoint is a mocked socket: when it receives the recv_string method, it replaces @buffer instance variable on e. Please have a look at the example code.

Tuesday, 7 January 2014

Protect your Hawt.IO ActiveMQ-5.9.0 console with LDAP

Starting from version 5.9.0, activemq is shipped with the hawt.io web console.

Out-of-the-box the credentials to access are admin:admin, istructions are at: $ACTIVEMQ_HOME/docs/WebConsole-README.txt.

In order to enable a LDAP based authorization, you need to modify the jaas conf file (default is: $ACTIVEMQ_HOME/conf/login.config) and a couple of Java Additional Parameters ($ACTIVEMQ_OPTS) which can be specified in various places, wrapper.conf, for example.

You also need a java LDAP library: ldaptive. Please copy the newest ldaptive jar file from http://www.ldaptive.org/download in your $ACTIVEMQ_HOME/lib.

login.config

The login.config should look like:
The cn=hawtio,ou=agents,dc=example,dc=org is a principal allowed to browse the groups' memberships.
Users allowed to access to hawt.io have to be members of the cn=the_admins_group,ou=groups,dc=example,dc=org group.

The LDAP server is ldap.example.org and it is contacted over TLS.

Java Additional Parameters

The relevant Java Additional Parameters are:
  • hawtio.realm=activemq: should match the key if config.login (activemq in the previous example);
  • hawtio.role=admins: group membership required. As the defaultRole membership is granted to the users found in the roleFilter, you need to match the defaultRole;
  • hawtio.rolePrincipalClasses=org.ldaptive.jaas.LdapRole: the java class of the role. The given value is correct for a ldaptive-granted role;
  • java.security.auth.login.config=%ACTIVEMQ_CONF%/login.config: location of the jaas config file.
These parameters can be specified in ./bin/activemq, in wrapper.conf or in /etc/default/activemq (Linux GNU/Debian).

Enable logging

This couple of lines in logback.xml can help you a lot:

Thursday, 1 August 2013

OpenLDAP ldap backend: SASL authentication

The problem

The OpenLDAP ldap backend acts as a reverse proxy to a LDAP server containing real data. The simple binds are simply verbatim transferred to the data server and users don't even feel there is a proxy in-between.
The problem is with SASL. With a SASL bind the proxy doesn't have a password to forward to the data server. Even if proxy authenticates user with GSSAPI or EXTERNAL, proxy obtains a dn but no password. So it has to perform an anonymous bind which is different from an authenticated one. This behaviour is warned by the log line:
ldap_back_dobind_int: DN="cn=admin,dc=example,dc=org" without creds, binding anonymously

Overview

The solution uses the id_assert directive in the ldap badabase section on the proxy in order to bind to the data server with a defined principal who then proxies to the original client identity thanks to the authzTo attribute.
The OpenLDAP need three modifies:
  • id_assert section in ldap database (proxy server)
  • creation of the id_assert principal with the authzTo attribute (data server)
  • enable authzPolicy to in cn=config (data server)

ldifs needed

To enable authzPolicy on the data server: This is necessary because OpenLDAP disregards authzTo attribute in a entry unless the global olcAuthzPolicy is set.
To enable id_assert on ldap database on proxy server: The id_assert is in effect only for authenticated users to avoid using a privileged bind for anonymous users.
The proxy user is defined as follow:

Check log entries

This is a log entry for the user "a_user" bound with GSSAPI requesting his own entry:
Log on proxy:
Log on data server: Note bind is performed by cn=proxy,ou=agents,dc=example,dc=org but then authorization is performed on behalf to "a_user".

Wednesday, 24 July 2013

OpenLDAP ldap backend as a proxy

Ldap backend works as a proxy: when a client searches data, proxy forwards request to ldap servers with real data, which are served to client. This is useful for:
  • high availability: ldap backend spots faulty servers and picks the first working in a list
  • firewalling: clients connect to a single IP no matter how many ldap server are involved.
Before using ldap backend, you have to enable it: create a ldif named 'add_module_ldap.ldif' and apply with: sudo ldapadd -H ldapi:/// -Y EXTERNAL -f add_module_ldap.ldif Now you are ready to create to database by inserting the following ldif. Now queries matching the basename "dc=example,dc=org" are forwarded to the first available server between ldap1.example.org or ldap2.example.org. The proxy might take some time to spot faulty server (maybe it has to wait for a timeout), but since the next call it forwards to the last used server, the first working one. Please note:
  • the "allow all" acl is required because ldap backend perform authorization. A request is fulfilled if both the proxy and the data server allow it. Serious acl are supposed to be on the data server only (it helps sanity);
  • remember to encrypt connection between proxy and data server with 'olcDbStartTLS: start'