You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 59 Next »

Name

Crowd as an LDAP Server

Version

1.0

Product Versions

Crowd v1.0.6

Author(s)

Robert Castaneda [CODEGEIST:CustomWare] , Daren Klamer [CODEGEIST:CustomWare]

Homepage

http://www.customware.net

Price

FREE! Priceless!

License

N/A

JavaDocs

 

IssueTracking

 

Download JAR

 

Download Source

Code, what code? This one is about re-use!

Description/Features

A layer to turn Crowd into an LDAP server

Motivation - a non-Atlassian product to integrate into our environment. The product supports LDAP authentication, we want to use our Crowd deployment as the central repository of users, rather than setting up an LDAP repository just for this application.

A picture is a thousand words - here is the end result in JXplorer of users listed from Crowd via LDAP:

The requirement is to have no Java/J2EE/Atlassian based products use crowd as the central authentication mechanism via LDAP. To achieve this, we have used Penrose - http://penrose.safehaus.org/ and have configured it to read user/password information from the Crowd database as well as implement a password decrypt/decode function in Penrose so that it can authenticate using the same passwords that are stored in Crowd without duplicating user information. A user in Crowd, is a user in LDAP. The diagram shows the setup below:

Crowd LDAP

Whilst not a plugin that runs within an Atlassian product, it's another solution that can bring outside technologies into the Atlassian world.

How an external application authenticates over LDAP can be different from one application to another. This example has been tested using Crowd itself, that is , using the Penrose LDAP server as a Crowd Directory service and a Crowd external Application setup to test against this directory.

At any time, Crowd can update their algorithm for storing passwords. The mechanism described here makes us of the fact that having access to the right data, a password can be reverse engineered/constructed from the Crowd database. If this ability changes in future, then this will need to be updated, probably to use the

Unknown macro: {SHA-512}

<pwd> type syntax.

As always, an application/infrastructure such as Crowd is only as secure as the infrastructure -database/os - that it runs on.

Steps to setup

  • We then create a Source. In Crowd, we created a View rather than accessing the tables directly. The main table that you need access to is REMOTEPRINCIPALCREDENTIALS

  • We then and add a New Dynamic Entry, not a "Dynamic Entry from Source". Within that entry definition, we define the source within the dynamic entry.

Code

The following code decrypts passwords stored in Crowd, note that you need to retrieve the RETRIEVE_ME_FROM_YOUR_CROWD_DATABASE parameter from your DB. To retrieve this parameter, execute the following SQL from the Crowd database:

select * from "SERVERPROPERTY" where "NAME" = 16

The code is below.

import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

            // Buffer used to transport the bytes from one stream to another
        byte[] buf = new byte[CODEGEIST:1024];

        try {
            byte[] hash = new BASE64Decoder().decodeBuffer( RETRIEVE_ME_FROM_YOUR_CROWD_DATABASE );
            SecretKey key = new SecretKeySpec( hash, "DES" );

            DESKeySpec paramSpec = new DESKeySpec( hash );

            Cipher dcipher = Cipher.getInstance( "DES" );
            dcipher.init( Cipher.DECRYPT_MODE, key );

            ByteArrayInputStream bis = new ByteArrayInputStream( new BASE64Decoder().decodeBuffer( thepwd ) );

            InputStream in = new CipherInputStream( bis, dcipher );

            // Read in the decrypted bytes and write the cleartext to out
            int numRead = 0;

            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            while( ( numRead = in.read( buf ) ) >= 0 ) {
                bos.write( buf, 0, numRead );
            }
            return new String( bos.toByteArray() ) ;
        } catch( Exception e ) {
            e.printStackTrace();
        }

Screenshots

  • No labels