Andreas Knecht

I needed a way to bulk add users from one group to another in Crowd this week. The problem was basically that not all members of a 'staff' group in Crowd were also members of a 'jira-users' group which was causing problems with logins in JIRA.

Since Crowd's UI doesn't support bulk operations yet, doing it via its Remote API was the only option. I decided to implement this in Ruby for no particular reason other than that I wanted to play with another language. Ruby turned out to be surprisingly quick to learn actually.

Read on for the full implementation details...

Ruby setup

Being a complete Ruby newbie I didn't know that Ruby (including SOAP4R the ruby soap library) comes pre-installed on OSX (Leopard). So I went ahead and installed it (again). I found out later that this is only needed on Tiger and Leopard users should use the installed version of Ruby. So here's the setup steps for Tiger :).

I first installed MacPorts which also required Apple's Xcode Tools to get gcc. XCode is found as an optional package on the OSX installation DVD.

Once I'd installed this, I installed Ruby following the instructions:

% port install ruby

Finally, I also needed to install SOAP4R:

% gem install soap4r --include-dependencies

Writing the script

First I generated my client scripts using wsdl2ruby:

% wsdl2ruby --wsdl http://localhost:8095/crowd/services/SecurityServer?wsdl --type client

Then it was time to write my script. There's two ways to do this. Interactive Mode or in a script. I found that the interactive mode was incredibly useful to learn the language and try out things. You can start the interactive shell by invoking:

% irb

Once I'd figured out how to do things in the interactive shell, I ended up putting it all together into the following script:

require "defaultDriver.rb"

# Set these for your crowd instance
crowdBaseURL = 'http://localhost:9999/crowd'
applicationName = 'demo'
applicationPassword = 'demo'
sourceGroup = 'staff'
targetGroup = 'users'

driver = SecurityServerPortType.new(crowdBaseURL + '/services/SecurityServer')
authCtx = ApplicationAuthenticationContext.new(PasswordCredential.new(applicationPassword), applicationName, [])

begin
        token = driver.authenticateApplication(:in0 => authCtx)
rescue
        print "Error logging in: " + $! + "\n"
        raise
end

begin
        group = driver.findGroupByName(:in0 => token.out, :in1 => sourceGroup)
        print "Group '" + sourceGroup + "' has " + group.out.members.size.to_s + " members. Are you Sure you want to continue ? (y/n)\n"
        choice = gets
        if choice.chomp != 'y'
                print "Goodbye!"
                Process.exit
        end
rescue
        print "Error retrieving group '" + sourceGroup + "':" + $! + "\n"
        raise
end


group.out.members.each do |member|
        begin
                driver.addPrincipalToGroup(:in0 => token.out, :in1 => member, :in2 => targetGroup)
                print "Added '" + member + "' to group '" + targetGroup + "'.\n"
        rescue
                print "Error adding '" + member + "' to group '" + targetGroup + "': " + $! + "\n"
        end
end

To invoke the script simply run ruby bulkcopyusers.rb.

I've attached a zip file with all the generated scripts, if you want to use it with Crowd or just play with Ruby. Given that this is my first ever Ruby script, I'd love to hear about any improvements .

Total time taken was about 1 hour, which is probably only marginally longer than it would have taken me to write a Java client to do the same thing.

1 Comment(s)

We're currently testing this python script from google that does perodic ldap->google apps API synchronization. This coupled with your new google apps SSO support in crowd 1.5 makes us very happy!

http://code.google.com/p/google-apps-for-your-domain-ldap-sync/

By rob terhaar at September 17, 2008 8:15 AM

Post a comment

If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.





Remember personal info?

Type the characters you see in the picture above.