Connect Drupal 7 and Github via Oauth

In a project where I am working on there is a need to connect Drupal with Github.

Github offers an interesting API which is based on the Oauth protocol like Google and Twitter.

The first thing to do is creating an account on Github and on the profile page add an application url even setup in localhost (like http://localhost/drupal). When done, you will receive a client id and a client secret which will be used by Drupal to connect as client.

I setup Drupal on my laptop via Xampp, which means creating quickly a user “drupal” with a database “drupal” via phpmyadmin and then extract Drupal in my htdocs folder (using drupal as folder name) and follow the instructions at http://localhost/drupal.

On Drupal you need download and setup the Oauth connector module which comes with some dependencies, in particular the Oauth module which can be used for Oauth2.

Once everything is setup you can start to configure and for this you can follow the steps in this guide for  Facebook:

with the data used from here (I just forked the original project):

as you can see there is a mapping to be done between the github profile attributes and the drupal profile attributes. Since the Github name attribute is optional I preferred to use the login attribute (you can see some attributes from my profile), so just change it in:

'name' => array(
'resource' => '',
'method post' => 0,
'field' => 'login',
'querypath' => FALSE,
'sync_with_field' => 'name',

Unfortunately the avatar will not be copied but you can contribute to the module :-)

When you will connect to Github you might experience 2 types of problem:

If everything goes fine, at the end you will have a github button at the login which redirect the user to Github and come back to Drupal.

Be careful that when you come back to Drupal you have a session cookie therefore the new user is authorized but, since Drupal by default blocks the user (because by default the administrator should authorize and the account should be confirmed by email), you cannot login with your account; also my Drupal doesn’t send emails. So I suggest to remove the cookie from your browser, login with the administrator and unblock the user (you will be able to login with the github account) and change the options in Drupal to allow people registering automatically without waiting that the administrator unblocks the user.

With the last changes you would expose Drupal to security issue but I didn’t try it a Drupal hosted on a website and with email confirmation.





Avoid XML Schema restrictions

I am back on XML Schema design and I do really like it !

One of the challenge that I am facing now is including or not the UBL metalanguage in my schemas (see some video on the oasis website), an Oasis standard, as you can deduce.

As you can see from this file:

UBL metalanguage has elements which are based on the UN/CEFACT elements, see:

So as you can see UN/CEFACT has ComplexType which are extended by adding optional attributes, while the UBL elements are sometime restrictions  on the attributes (by making them required) and sometimes the elements are just extended giving a freedom in a later moment to choose what to add.

Independently from  the current problem, it happens that we might not need all the attributes or simply all the elements for our schema.

So either we add restrictions or we copy the elements that we need in our schema but simplified.

Adding restrictions can be possible in two ways:

1) Restrict on the patterns, like the max length of an element, they are so called facets, see:

2) Restrict on the number of elements or attributes, in the case of the attributes  we need to make them prohibited

Conceptually both are restrictions based on an another type and this creates a problem in Object Oriented languages, like Java (hence the tittle of this post) which supports extensions (at the end a restriction is a sort of extension of a base object with some changes).

Jaxb is the official standard used for databinding XML elements to Java objects which relies on XJC for the conversion. Such standard adds Java annotations to associate XML elements to Java objects. Further, Jaxb relies on the validator of the marshaller by using the setSchema() method, see for example the post of Blaise Doughan, so in any moment you can validated your object against the schema to be sure before sending out your xml message.

For the facets, Jaxb doesn’t create annotations, there is still an open issue where 2 subgroups are working to solve it but still none of them are officially approved:

Other data bindings work on simple restrictions like enumerations (see Jibx) or numeric type and enumerations (see Xmlbeans, now archived).

You need also to consider that facets can change in the future (the max length could be extended from 100 characters to 200), so which impact has changing the xml schema? Since Jaxb doesn’t generate annotations for facets you don’t need to change the java objects but other databindings might be.

For the restriction on the the number of elements/attributes this CANNOT be reflected in a Object Oriented language because it is not possible to restrict an extended class on inherited properties. Therefore I suggest to copy simplified elements (by keep only those mandatory and removing the optionals), in this way:

  1. you have less dependency
  2. the developer has less method generated (just those needed)
  3. you keep compatibility at the minimum if you want to convert the copied object into the original objects

Therefore I would recommend to avoid restrictions if possible, you can keep them for the sake of validation but you need to think about the impact on the objects generated with the databinding libraries. Such recommandation is also expressed by the HP XML schema best practices (search for “restrictions for complex types”) and in Microsoft xml schema design pattern.




Mailman and OpenDJ

For a project I started to add mailing list functionality to the development infrastructure, as requirement the mailing list should make use of the LDAP service.

In a previous article I explained that I chose OpenDJ to manage LDAP users and groups and for the management of mailing list I chose Mailman to be used with Postfix. As alternative I could have chosen Sympa but since Mailman is packaged already in many distribution and it doesn’t have many requirements like Sympa has, I preferred to go for Mailman. The drawback is that Mailman doesn’t come with LDAP support and I found a script which I adapted and uploaded on my github account.

To manage mailing list in OpenDJ you could opt for 3 ways:

  1. use the mailGroup object class
  2. use the groupOfUniqueNames object class together with the extensibleObject class
  3. customize your schema

OpenDJ has the schema definition of mailGroup coming from the Solaris system which allows  to enter the mail of the group and the mail of the users by using the attribute mgrpRFC822MailMember.

But…most of the time you will already have your users recorded in LDAP (using most probably the inetOrgPerson) therefore, instead of directly inserting users mail you would like to insert the DN of each user, in this way even PHPLdapAdmin allows you to insert easily each user without pasting email addresses.

Therefore I went for groupOfUniqueNames which allows me to define users with their DN and, by adding the extensibleObject class, I have the possibility to add the mail attribute.

In this way if I have already defined a group I can use it as well for mailing list without replicating information (e.g. mail address for each user with mailGroup).

After that I installed and configured Mailman and, as described above, I used a perl script which:

  1. extracts those groups that are groupOfUniqueNames and have a mail attribute set (&(objectClass=groupOfUniqueNames)(mail=*))
  2. extract all the users uniqueMember belonging to the group which have an mail address set and are not disabled (&(mail=*)(!(ds-pwp-account-disabled=*)))
  3. creates a mailing list which will have as name the CN group attribute (saved inside the variable $listname)

If you execute the script with the command:


you will get an output like:

Processing list: jenkins-users-mail
Found member: emidio
List jenkins-users-mail does not exist.
Creating new list jenkins-users-mail.

Syncing jenkins-users-mail...
Added :

enjoy creating mailing lists !

Export Crowd users and groups to ldap

I need to migrate users and groups created in Atlassian Crowd to OpenDJ, an open source LDAP server written in Java fork of OpenDS; in this way Crowd will act just as SSO and it will rely on OpenDJ to store users.

Crowd can rely on several LDAP servers but it doesn’t have tools to export users and groups to ldap so I created a couple of queries (my database is PostgreSQL) to export in ldif files:

COPY(select 'dn: cn=' || user_name || ',ou=users,dc=my,dc=website,dc=com' || chr(10) ||
'objectClass: inetOrgPerson' || chr(10) ||
'objectClass: organizationalPerson' || chr(10) ||
'objectClass: person' || chr(10) ||
'objectClass: top' || chr(10) ||
'mail: ' || lower_email_address || chr(10) ||
'uid: ' || user_name || chr(10) ||
'cn: ' || user_name || chr(10) ||
'givenName: ' || first_name || chr(10) ||
'sn: ' || last_name || chr(10) ||
'displayName: ' || display_name || chr(10) ||
'userPassword: ' || credential || chr(10) || chr(10)
from cwd_user) TO '/tmp/users.ldif';

Of course you can customize the query to adapt to your needs, have in mind that the userPassword most probably is stored in PKCS5S2 format (you can see that the passwords extracted start with {PKCS5S2} prefix, see Crowd hashes), which is the default for Crowd or called Atlassian-security. In this sense only ApacheDS currently (2.0.0-m16) supports the same format while for OpenDJ there is a change to be done to the pbkdf2 storage scheme. It is up to you if you prefer to reset passwords or try to keep them during the migration.

As small parenthesis I have been asking to those people of Crowd about their connector for ApacheDS, since their connector supports ApacheDS 1.5.x (not anymore maintained by ApacheDS developers) and they are not sure to spend time in updating such connector for version 2.0, see my question on Atlassian Answers. An interesting thing to know is that also WSO2 Identity Server has bundled ApacheDS 1.5.7, you can see it also in the source code but you can connect it to OpenDJ.

In case your Crowd was setup with SSHA1, you can also use Openldap, see FAQ.

For the groups the query would be something like:

COPY(select 'dn: cn=' || parent_name || 'BASE_GROUPS' || chr(10) ||
'cn: ' || parent_name || chr(10) ||
'objectClass: groupOfUniqueNames' || chr(10) ||
'objectClass: top' || chr(10) ||
'uniquemember:' array_to_string(array_agg(child_name),',')
from cwd_membership group by parent_name) TO '/tmp/groups.ldif';

As you can see I used the functions array_to_string and array_agg integrated in PostgreSQL to create the list of users. These users will not have their base (,ou=users,dc=my,dc=website,dc=com), so, after executing the query, you can apply some regular expression (I used Notepad++) to replace the regex “([,])” with “,ou=users,dc=my,dc=website,dc=com\nuniquemember: cn” which replaces all the “,” inserted with the query with their base. At the end, I replaced BASE_GROUPS with “,ou=groups,dc=my,dc=website,dc=com“.

You can import the ldif files with PHPLdapAdmin or directly in OpenDJ with import-ldif command, keep in mind that you need to allow pre encoded passwords before importing.

Enjoy the migration !




Nexus maven repository with Apache as proxy and OpenDJ for authentication

For a client I have recently setup a nexus (oss) maven repository with apache proxy/reverse proxy and OpenDJ to provide LDAP authentication.

Nexus, which competes with Artifactory as maven repository, by default is waiting on port 8081 with the context path /nexus, which means that you can connect to it to the address http://localhost:8081/nexus (admin/admin123)

Having defined the name of my machine as maven I first configured Apache as proxy pointing to Nexus in this way:

ProxyPass         /nexus http://maven:8081/nexus
ProxyPassReverse  /nexus http://maven:8081/nexus

Having configured Apache to accept only https connections to be forwarded to Nexus in http (so https–>Apache–>http–>Nexus), I need to add before the ProxyPass directive the following RequestHeader:

RequestHeader set X-Forwarded-Proto “https”

in this way, the Nexus zip version, which is bundled with the servlet container Jetty 8.1.11 (which from the version 7.2.0 understands x-forwarded-proto header, see also the commit related) it will reply with the connection option (forwarded=true), see below the default configuration (in /nexus/config/jetty.xml):

<Set name="host">${application-host}</Set>
<Set name="port>${application-port}</Set>
<Set name="forwarded">true</Set>

Now we add the ldap authentication, we go under Administration -> Server and add the OSS LDAP Authentication Realm to the Selected Realms.

I have OpenDJ listening on port 1389 (default), so we go under Security -> LDAP Configuration, we set the following parameters:

Protocol ldap
Hostname opendj
Port 1389
Search Base dc=my,dc=example,dc=com
Authentication method Simple Authentication
Username cn=admin
Password mypassword
User Element Mapping
Base DN ou=users
Object Class inetOrgPerson
User ID Attribute uid
Real Name Attribute cn
E-Mail Attribute mail
Group Element Mapping
Group type Dynamic groups
Member of Attribute isMemberOf

The last 2 lines are optional to Static groups, but since OpenDJ allows to use the isMemberOf attribute, I preferred to use Dynamic groups (see Nexus documentation). For static groups you can check out also this article based on OpenDS on which OpenDJ is based on.

Now if you click on the Check User Mapping button you should see the list of users and groups retrieved from OpenDJ.

The last step would be add roles to the user so we go under Security ->Roles -> Add…->External Role Mapping and we select the LDAP group which will act as nexus administrators and we add all the roles for the group. So we logout and then we login with the nexus ldap administrator.





Allow SSH users to change their passwords on OpenDJ

For a client I started to put in place a connection from ssh to OpenDJ, which I chose for previous reasons.

To setup ssh with PAM and LDAP you can follow several tutorials, the one I found more easy to follow is:

Depending on your security policy, you could need to allow ssh users to change their passwords with the passwd command, to do so the file /etc/pam.d/sshd has the following include:

# Standard Un*x password updating.
@include common-password

so a common configuration for the file common-password would be:

password        [success=2 default=ignore] obscure sha512
password        [success=1 user_unknown=ignore default=die] try_first_pass
password        requisite             
password        required              

As we can see when we change a password we check first the user in the system ( If the change succeed we skip the next 2 lines (success=2) and we allow the change ( If doesn’t succeed we check on ldap ( and if the operation succeed we skip the next line (success=1) and we allow password change (  If also the password change on ldap fails then we deny the password change (

Further, as we can see on PAM code, the pam-ldap package tries to update the attribute shadowLastChange, which

  • on unix system would correspond to the 3rd value in the /etc/shadow file  which is the number of days, (since January 1, 1970) since the password was last changed
  • on LDAP system, it is defined in the RFC 2307 as an attribute of the object shadowAccount, together with other values for password expiration, see brief description, similar to the /etc/shadow.

Therefore to allow PAM changing a password on OpenDJ we need to:

  • add the attribute shadowLastChange to the user, you can use PhpLdapAdmin to add the shadowAccount object class to your Posix users first.
  • add an ACI in OpenDJ to allow changing shadowLastChange to the binded user

You can learn how to create an ACI on OpenDJ here and also from the Oracle website.

Concerning the ACI for the password change, you could write in a ssh-shadow.ldif file something like:

dn: ou=People,dc=my,dc=domain,dc=com
changetype: modify
add: aci
aci: (targetattr = "shadowLastChange") (target = "ldap:///ou=People,dc=my,dc=domain,dc=com") (version 3.0; acl "change shadow"; allow (write) (userdn = "ldap:///self");)

where you allow the binded users (ldap:///self) to modify (write) the attribute shadowLastChange, which is similar to example reported on the OpendJ documentation to change own password.

Apply then the changes with the command:

./opendj/bin/ldapmodify -h myhost -p 1389 -D "cn=Directory Manager" -W -c -f ssh-shadow.ldif

Once the password is changed with passwd command, you can verify that the value is changed in OpenDJ with PhpLdapAdmin and also check online the correspondent date.

To delete the ACI just replace “add: aci” with “delete: aci” in the file and re-execute ldapmodify command.