How to customize GitLab to support OpenID authentication

Rational

While setting my GitLab servers I had to perform a number of customizations, the main one being to support OpenID and the method described here could thus be used to do any kind of customization.

If like me you try to use the software packages that come with your preferred Linux based operating system you’ll find the “official” installation guide for GitLab rather untypical. This installation guide seems to totally ignore Linux good practices such as separating configuration, programs and data into /etc, /usr and /var and installs everything under a standard user directory.

A benefit of this “simplification” is that the whole GitLab installation is a git clone of the GitLab source code (that would probably be more difficult if stuff were spread into multiple locations). And the beauty of using git clones is that updates are basically a matter of pulling a new version from the remote repository.

And if you need to “customize” the code you can take advantage of git and create you own local branch(es) which you can push into you own remote repository if you want to share the same customization between multiple GitLab installations.

Disclaimers

  1. I have been following these principles for an initial installation of GitLab 6.1 and upgrades to 6.2 and 6.3 without any major issues but of course I can’t guarantee that it will be the case for you: use at your own risk!
  2. Many thanks to Stephen Rees-Carter for a most helpful post that got me started.

In Practice

Initial installation

Start by a full installation following the “official” installation guide for GitLab and check that everything is running as expected. You could probably save some time by modifying the source during this initial installation but if anything went wrong you’d be in trouble to determine if this is a consequence of your modifications or anything else.

Stop the server

$ sudo service gitlab stop

Create a local branch

It’s a matter of taste but I tend to prefer running commands as the GitLab user (git if you’ve followed the installation guide to the letter) than prefixing them with sudo -u git -H as shown in the installation guide. Of course gitlab-shell will block you if you try to ssh directly as the GitLab user but you can  become the git-lab user using sudo and su:

$ sudo su - git

To create a local branch called openid and switch to this branch:

~$ cd gitlab
~/gitlab$ git checkout -b openid

 Add the omniauth-openid gem

Edit Gemfile to add gem ‘omniauth-openid‘ after gem ‘omniauth-github‘ so that it looks like:

# Auth
gem "devise", '~> 2.2'
gem "devise-async"
gem 'omniauth', "~> 1.1.3"
gem 'omniauth-google-oauth2'
gem 'omniauth-twitter'
gem 'omniauth-github'
gem 'omniauth-openid'

After this update you’ll need to create a new bundle. To do so you have to run the command bundle install as root (running sudo as a user which has enough rights). This will update the Gemfile.lock file and other resources which should belong to the GitLab:

~/gitlab$sudo bundle install
~/gitlab$sudo chown -R  gitlab.gitlab .

At that point, git status should tell you that you’ve updated both Gemfile and Gemfile.lock and you can commit this first step:

~/gitlab$ git commit -a -m "omniauth-openid gem installed"

Configuration

Update config/gitlab.yml to enable omniauth:

  ## OmniAuth settings
  omniauth:
    # Allow login via Twitter, Google, etc. using OmniAuth providers
    enabled: true

In a perfect world you should be able to configure OpenID as an omniauth provider here but unfortunately, the code that handles these definition (located in config/initializers/devise.rb) requires mandatory app_id and app_secret parameters used by proprietary protocols to lock users. OpenID doesn’t use these parameters and we’ll define OpenID providers directly in the code.

Defining OpenID providers

Update config/initializers/devise.rb to add the definition of the OpenID provider(s) so that it looks like:

...
      name_proc: email_stripping_proc
  end
# Update starts here
#  require "openid/fetchers"
  OpenID.fetcher.ca_file = "/etc/ssl/certs/ca-certificates.crt"

  config.omniauth :open_id,
    :name => 'google',
    :identifier => 'https://www.google.com/accounts/o8/id'

  config.omniauth :open_id,
    :name => 'openid'
# Update ends here
  Gitlab.config.omniauth.providers.each do |provider|
...

(Add the first declaration only if you want to offer OpenID authentication to Google users)

Define how these providers should be handled

Update app/controllers/omniauth_callbacks_controller.rb to include these definitions:

# Update starts here
  def google
     handle_omniauth
  end

  def openid
     handle_omniauth
  end
# Update ends here

  private

  def handle_omniauth

Declare these providers as “enabled social providers”

At that point, users should be able to login using OpenID if the relevant information was available in the database and we need to enable the user interface which will put these info in the database.

Update app/helpers/oauth_helper.rb to add OpenID (and google if you’ve defined it) to the list of “enabled_social_providers“:

  def enabled_social_providers
    enabled_oauth_providers.select do |name|
      [:openid, :google, :twitter, :github, :google_oauth2].include?(name.to_sym)
    end
  end

This list was initially limited to [:twitter, :github, :google_oauth2].

Disable protect_from_forgery in omniauth_callbacks_controller.rb

At that point, profile/account pages should present a list of “social accounts” including Google and OpenID. Unfortunately if you click on one of these buttons the authentication will succeed but the database update will be blocked by the protect_from_forgery feature.

This issue is documented in stackoverflow and GitHub and a workaround is to switch this feature in the controller that handles the authentication.

Update app/controllers/omniauth_callbacks_controller.rb to comment the third line and require to skip this:

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  # Update starts here
  #protect_from_forgery :except => :create
  skip_before_filter :verify_authenticity_token
  # Update ends here

  Gitlab.config.omniauth.providers.each do |provider|

Start the server and test

$ sudo service gitlab start
$ sudo service nginx restart # or sudo service apache2 restart

OpenID authentication should work fine at that point.

Commit

~/gitlab$ git commit -a -m "Ready for OpenID..."

Upgrades

To upgrade your GitLab installation you’ll need to merge the new version into your openid branch before you can follow the upgrade guide. For instance, to upgrade to version 6.3 I have typed:

~/gitlab$ git fetch
~/gitlab$ git checkout 6-3-stable # to have a look at the new version
~/gitlab$ git checkout openid # back to the local branch
~/gitlab$ git merge 6-3-stable

You may run into merge conflicts. During the upgrade to 6.3, the Gemfile had been updated and as a result of this update, Gemfile.lock was in conflict.

To fix this specific issue I have run the bundle install command again:

~/gitlab$sudo bundle install
~/gitlab$sudo chown -R  gitlab.gitlab .

When you’ve fixed your conflicts, you need to add the files in conflict and commit:

~/gitlab$ git add Gemfile.lock 
~/gitlab$ git commit -m "Merging 6.3"

From that point you should be able to follow standards upgrade instructions.

Using your own remote directory

If you need to install several servers with the same customization, you may want to push your branch to a remote directory.

To do so, you must define a new remote and specify whenever you push to that directory, for example:

~/gitlab$ git remote add myremote git@gitlab.example.com:gitlab/custom.git
~/gitlab$ git push myremote openid

Note that of course if you want to pull/push from the GitLab server you are working on it would need to be up and running ;) !

To install new servers you can now follow the standard installation guide just replacing the initial git clone by a clone of your own remote directory.

Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites

From Trac to GitLab

I have been using Trac since ages and I like its simplicity compared to systems such as Jira but I must say it looks like a dinosaur compared to GitHub

I like GitHub but I am also a strong believer that the web should stay decentralized and have been searching an open source alternative that I could host on my servers for a while.

The latest version of GitLab is a perfect solution for my needs: previous versions were focused on private projects but version 6.2 introduces the support for public projects that was missing in previous versions.

I have installed GitLab at https://gitlab.dyomedea.com/ and I have started using it to publish my presentation at XML Amsterdam.

My plan is now to slowly migrate my open source projects between Trac and GitLab and I have found a couple of Python scripts that may help for this process:

I have consolidated these two scripts and the result is available as trac-to-gitlab which is of course… published on GitLab!

One of the things I really like with git is that at the bottom of the network of changes you can see the initial history of the two scripts with the commit dates and names of their authors.

I hope that trac-to-gitlab may be useful to others and be similarly cloned into other projects!

Of course, comments, issues and merge requests are welcome.

Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites