2010.11.03

Tutorial: Secure Git And Jira Integration (5/7)

Stéphane Bagnier

This article is part of a series about the complete installation of the Atlassian collaborative software suite behind a proxy with SSL everywhere. If you want to understand the goal of this tutorial, you should report to the introduction article. From there, you would also have access to the installation of the basis of the Atlassian applications with Crowd, Confluence, and Jira.

This article describes how to set up Git for Antelink's dev team. The aim is to integrate this SCM to the Atlassian applications, with a solution that simplifies Git users management and links them to the application users. The first task is to install and configure Git, then you have to install Gitolite to manage Git users and provide access control to the company's server hosting Git private repositories. The third step is to connect Jira and Git.

Git

Git is the distributed revision control system used by Antelink's developers team.

Installation

It is necessary to have the Git version 1.6 at least, for compatibility reasons with Fisheye 2.3.4. Since Debian X is delivered with Git 1.5, Antelink uses Lenny Backports. You have to edit the file /etc/apt/sources.list and add these lines, as root:

vi /etc/apt/sources.list

1
2
deb http://www.backports.org/debian/ lenny-backports main
deb-src http://www.backports.org/debian/ lenny-backports main
aptitude -t lenny-backports install git-core

If you have trouble with the installation, try adding a key to the list of keys in the apt repository, to authenticate the packages:

Then reinstall the package git-core by running the last aptitude command.

Configuration

This part is optionnal because Git is configured by default. However, if you keep the default configuration, you will have the next message displayed each time you commit:

Committer: john.doe
Your name and email address were configured automatically based on your username and hostname. Please check that they are accurate.  
You can suppress this message by setting them explicitly:  
git config --global user.name "Your Name"  
git config --global user.email you@example.com 

 

If the identity used for this commit is wrong, you can fix it with: 

    git commit --amend --author='Your Name ' 

To avoid that, configure Git, as antelink:

git config --global user.name antelink
git config --global user.email john.doe@mailprovider.com
git config --global core.editor vi

Gitolite

I needed a tool to manage Git users and provide access control to the company's server hosting Git private repositories, so our developers and only them could access the Git repositories.

One solution was to create a Unix user for each developer. They would then access the repositories over SSH as described here. But it is inconvenient and not easy to manage that many Unix users.

So I tried Gitolite, the successor of Gitosis, that turned out to be rather satisfying.

It is quite secure because it was specifically created to be used in corporate environments. It is based on an exchange of SSH public keys to add a new user, instead of adding an actual Unix user. And a configuration file allows you to specify the rights of each user: read and write rights, not only at the repository level, but at the branch level within repositories.

I found Gitolite rather powerful, easy to use and well documented. Don't hesitate to visit its official wiki to learn more, because I will only explain what is necessary to integrate Git to the Atlassian applications.

Installation

Different ways to install Gitolite are documented in the official website. I chose the from-client method because it forces you to exchange the SSH public key before continuing the installation. It consists in installing Gitolite from a client to the server. In this configuration, the client and the server are on the same machine, but it doesn't change anything.

Prerequisites:

Gitolite requires Git 1.6 at least to be installed on the client machine, which is the same as the server in this case. If later, you have trouble with Gitolite, remember to check if you have the right version of Git with the command:

git --version

Create the Unix user git:

First of all, you need to create a "hosting user" on the server. It is important because developers will be able to manage Git repositories thanks to him: they will all connect to the server as this user, after sending him their SSH public key. This way, you will have a unique Unix user and as many developers i.e. remote users as you want.

You can name this user git, for instance, and create him as root as follows:

useradd -d /home/git -m git 
passwd git
New UNIX password: git-passwd
Retype new UNIX password: git-passwd
passwd: all authentication tokens updated successfully 

Configure SSH:

The user git must be allowed to use SSH. After installing the Debian packages for SSH, all users are authorized by default. So if you haven't tampered with the SSH configuration files, you have nothing to do. Otherwise, open the file:

 

vi /etc/ssh/sshd_config

The entry AllowUsers indicates the users allowed to use SSH. If no such entry exist, add it, or else add git to the list,as root:

AllowUsers antelink git

Restart the SSH server:

/etc/init.d/ssh restart

Then create a public/private key pair for your user, if he doesn't have one. Since I named my user antelink, I ran the following commands as antelink himself:

ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/antelink/.ssh/id_rsa): /home/antelink/.ssh/id_rsa
Created directory '/home/antelink/.ssh'.
Enter passphrase (empty for no passphrase): (Empty)
Enter same passphrase again: (Empty)

The last step is to add your user's public key to git's authorized keys. Here's how I did for antelink

:

ssh-copy-id -i /home/antelink/.ssh/id_rsa.pub git@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established. 
RSA key fingerprint is *********************. 
Are you sure you want to continue connecting (yes/no)? yes 
Warning: Permanently added 'localhost' (RSA) to the list of known hosts. 
git@localhost's password: 
Now try logging into the machine, with "ssh 'git@localhost'", and check in: 
  .ssh/authorized_keys 
to make sure we haven't added extra keys that you weren't expecting. 

You can make sure that your user is authenticated on the server as a Git user without being asked for a password. The following command:

ssh git@localhost pwd

must display:

/home/git

Get Gitolite's source files:

We can now get Gitolite, using…Git! Do as the user antelink:

cd /home/antelink
git clone http://github.com/sitaramc/gitolite.git gitolite-source
Initialized empty Git repository in /home/antelink/gitolite-source/.git/
remote: Counting objects: 2628, done.
remote: Compressing objects: 100% (867/867), done.
remote: Total 2628 (delta 1767), reused 2570 (delta 1728)
Receiving objects: 100% (2628/2628), 575.30 KiB | 943 KiB/s, done.
Resolving deltas: 100% (1767/1767), done.

cd /home/antelink/gitolite-source/src/
./gl-easy-install -q git localhost antelink
you are upgrading (or installing first-time) to v1.5.4-6-gf0c280c
setting up keypair...
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): (Let it empty)
Enter same passphrase again: (Let it empty)

When running these last two commands, many informations about the following steps and Gitolite are? displayed. I advise you to read eveything to understand Gitolite.

Here are the URLs to access the repositories:

gitolite:depot.git for antelink,
git@SERVER_IP:depot.git for all others users.

 

You can check if Git's administration repository was correctly created:

cd /home/antelink/gitolite-admin/
git --no-pager log --stat

The result must be something like:

commit b0c228d3f66e716a503af83b0e658205637a31d1 
Author: git  

Date:   Thu Jul 22 13:19:51 2010 +0200 

    start 

 conf/gitolite.conf  |   10 ++++++++++ 
 keydir/antelink.pub |    1 + 
 2 files changed, 11 insertions(+), 0 deletions(-) 

 

Administration

How the configuration works:

A repository gitolite-admin is created on the server, and cloned in antelink's personal directory. This repository is only for Gitolite configuration. It includes two files:

  • conf/gitolite.conf: Gitolite configuration files, including the repositories, the users, groups and their rights.
  • keydir/: a directory for the users public keys.

To configure Gitolite, open the directory /home/antelink/gitolite-admin and modify these files. You then have to validate the changes, by pushing them to the admin repository owned by the user git.

This is how you validate the changes in conf/gitolite.conf, for instance:

cd /home/antelink/gitolite-admin/
git add conf/gitolite.conf
git commit -m "add repository depot1"

If the file is modified for the first time, do:

git push origin master

Otherwise:

git push

Remember that you have to do that each time you change the settings of users, groups and repositories!

 

Add a user:

Let's add the user john.smith, as an example.

john.smith must have a public key. If he doesn't, he must create one as described in a previous part named "Configure SSH".

Then john.smith must send its public key to antelink who will:

  • Copy it as john.smith.pub in the directory /home/antelink/gitolite-admin/keydir/
  • Commit and push the changes to validate them:

 

cd home/antelink/gitolite-admin/
git add keydir/john.smith.pub
git commit -m "add user john.smith"
git push

You can add a second public key for john.smith:

It is indeed possible for every user to have multiple keys. This way, a developer can authenticate and use Git from different machines: his computer at work, at home, etc.

To do that, ask john.smith to send you the new public key, then:

Rename the key file as john.smith@client_ip.pub where client_ip is the IP address of the machine john.smith want to authenticate from. Place it in the directory /home/antelink/gitolite-admin/keydir/. Then validate the changes.

Add john.smithjohn.smith@client_ip to the lists defining users rights in conf/gitolite.conf, and validate the changes.

 

Add a group

Let's create a new group called developers and let's add john.smith in it:

cd /home/antelink/gitolite-admin/
vi conf/gitolite.conf
@developers = john.smith

Remove a repository:

Let's remove the repository testing that comes by default with Gitolites' files:

vi /home/antelink/gitolite-admin/conf/gitolite.conf

Remove the lines:

repo testing 
    RW+                 = @all 

Validate the change:

cd /home/antelink/gitolite-admin/
git add conf/gitolite.conf
git commit -m "rm repo testing"
git push origin master

As the user git, remove the repository's directory:

rm -rf /home/git/repositories/testing.git/

Add an empty repository:

Let's add a repository named MyRepo as an example. As antelink, add the following lines to the file gitolite.conf:

vi /home/antelink/gitolite-admin/conf/gitolite.conf
repo MyRepo
    RW+                 = antelink @developers

The second line means that antelink and users of the developers group have read and write rights on the repository MyRepo.

Validate the change:

cd /home/antelink/gitolite-admin/
git add conf/gitolite.conf
git commit -m "add repository MyRepo"
git push

Add an existing repository to Gitolite:

Suppose that you want to add an already existing repository MyRepo which is in /home/antelink/git/MyRepo/.

First you have to create an empty repository MyRepo, as seen before. Then copy the content of the real repository MyRepo to the empty repository MyRepo in Gitolite:

 

cd /home/antelink/git/MyRepo
git push --all gitolite:MyRepo 

Usage samples

There are many ways to clone a Git repository created via Gitolite.

As explained in the official documentation, normal users can do:

 

git clone git@infra.antelink.com:MyRepo

And Gitolite's administrator (antelink, in my case) have to do:

git clone gitolite:MyRepo

If you want to integrate Git and Jira, you will need different URLs to access your repositories. I'll tell you more about that in detail later.

Uninstallation

Uninstall Gitolite:

If you have trouble installing Gitolite, you might need to remove it in order to install it again. Here is the process:

Remove the paragraph starting with host gitolite in /home/antelink/.ssh/config then remove Gitolite's administration files:

rm -rf /home/antelink/gitolite-admin

Then you have to remove the key added by Gitolite to git's authorized keys file. You do that by removing the lines between # gitolite start and # gitolite end in this file, as the user git:

vi /home/git/.ssh/authorized_keys

And remove Gitolite's files from the "server" side:

rm -rf /home/git/.gitolite
rm -rf /home/git/.gitolite.rc
rm -rf /home/git/repositories/gitolite-admin.git

Uninstall Gitolite completely:

Proceed as in the previous paragraph, then remove the repositories you have created:

rm -rf /home/git/repositories/MyRepo

Now you should have all the users that will access your Git repositories defined in Gitolite. The next step is to install Git, create your repositories then link these users to Jira users. You will notice that the users base is duplicated between Gitolite and Crowd (Crowd users and Jira users are the same).

It is a weekness of my installation. If you prefer using a centralized users database, you can put all the user information in an LDAP directory, which you integrate to Crowd and tell Gitolite to use.

Git & Jira

Git and Jira for secure installation Atlassian

 

 

 

 

 

This integration will let you manipulate Jira issues and transform their workflow through simple Git commands. It was a real brain-teaser for me to come up with a solution that enables that, because Jira doesn't officially support Git. I had to try at least three solutions before deciding to write a script of my own:

The first solution was the git-jira-hook plugin but it had a known limitation: the command to mark Jira issues as resolved didn't work.

So I considered using the Jira Git Plugin, but it didn't officially support Jira 4.1 and lacked of documentation, so I was unable to configure it.

Then I tried something else: Actioning issues from commit messages is an available feature in JIRA Studio. I thought I hit the jackpot. But it didn't work outside Jira Studio.

There seemed to be a way to integrate Jira and Git through Fisheye, but I couldn't find more informations about it or make it work.

At last, I came across the Jira Command Line Interface plugin (CLI), which enables a remote access to Jira. It provides Unix commands to modify the workflow of Jira issues. It was exactly what I wanted and all I had left to do was write a hook for Git that runs after each Git commit, and calls the Jira CLI commands if the commit message has the right form. For instance, the commit message "TP-1 close" makes Jira CLI run a command that closes the Jira issue named TP-1.

The only problem is that this solution requires a client-side installation, unlike what was done until now. Each developer, who wishes to access Jira from the terminal, will have to install Jira Command Line Interface on his machine, and add a script to his local copy of the Git repository.

It would be ideal to install everything on the server and spare the developers that trouble. But I'm running out of ideas: I don't know how to make a Git push trigger a server-side hook, and mostly how to send the server the commit message.

Now I am going to explain you how I put in place this final solution, on the client side. But don't hesitate to write me a comment if you know how to solve the last issues, or if you have a better solution to integrate Jira and Git. I would gladly update this article accordingly.

Now let's start the installation!

Before anything, make sure you have Java 1.5 at least installed on all your client machines. It is a requirement of Jira CLI.

Then you can start the installation of the Jira Command Line Interface plugin and the configuration as the user antelink:

wget https://plugins.atlassian.com/server/1.0/download/pluginVersion/14383 -P /home/antelink/app/
unzip /home/antelink/app/jira-cli-1.5.0-distribution.zip -d /home/antelink/atlassian/app/
vi /home/antelink/atlassian/app/jira-cli-1.5.0/jira.sh

You have to replace this line:

java -jar release/jira-cli-1.5.0.jar "$@"

with:

java -jar release/jira-cli-1.5.0.jar --server https://jira.antelink.com --user admin --password admin-passwd "$@"

You have to replace admin with the name of the person in charge of the project associated to Git in Jira, and admin-passwd with its password. And, of course, https://jira.antelink.com with your application URL.

Because the file jira.sh contains admin's password in Jira, you need to prevent other users from reading or writing in it:

 

chmod o-rw /home/antelink/atlassian/app/jira-cli-1.5.0/jira.sh

Now that the plugin is installed and configured, you can create the script and make it executable:

vi /home/antelink/git/MyRepo/.git/hooks/commit-msg
#!/bin/bash 

cat /home/antelink/git/MyRepo/.git/COMMIT_EDITMSG | { read issue command other; 

        cd /home/antelink/atlassian/app/jira-cli-1.5.0/ 
        ./jira.sh --action login 

        res=0 
        step=0 
        if [ "$command" == "close" ]; then 
                echo k; 
                step="2" 
        elif [ "$command" == "closeResolved" ]; then 
                step="701" 
        elif [ "$command" == "startProgress" ]; then 
                step="4" 
        elif [ "$command" == "stopProgress" ]; then 
                step="301" 
        elif [ "$command" == "reopen" ]; then 
                step="3" 
        elif [ "$command" == "open" ]; then 
                step="Open Issue" 
        elif [ "$command" == "resolve" ]; then 
                step="5" 
                if [ "$other" == "fixed" ]; then 
                        res="1" # equivalent to res="fixed" 
                elif [ "$other" == "wontfix" ]; then 
                        res="2" 
                elif [ "$other" == "duplicate" ]; then 
                        res="3" # equivalent to res="duplicate" 
                elif [ "$other" == "incomplete" ]; then 
                        res="4" # equivalent to res="incomplete" 
                elif [ "$other" == "cantreproduce" ]; then 
                        res="5" 
                fi 
        fi 

        if [ "$step" != "0" ]; then 
                if [ "$res" != "0" ]; then 
                        ./jira.sh --action progressIssue --issue $issue --step $step --resolution $res 
                else 
                        ./jira.sh --action progressIssue --issue $issue --step $step 
                fi 
        fi 
        ./jira.sh --action logout 

} 

Then make it executable:

chmod +x /home/antelink/git/MyRepo/.git/hooks/commit-msg 

You can start using the integration:

cd /home/antelink/git/MyRepo/
git commit -a -m "TP-1 close"

If you have something like:

k50OYp5VkJ 
./jira.sh --action progressIssue --issue TP-1 --step 3 --resolution 
Successfully progressed issue: TP-1 with step '3' 
4V9mI06TLa logged out 

It means that the issue status was changed, so the integration is working!

You can also check the issue status via the Jira web interface.

Here is the special syntax you have to use:

Commit messages must be of the form: « TP-1 close ».

The first word is the name of the issue to update, and the second one is a command that can be one of the following:

close Close an open issue
closeResolved Close a resolved issue
startProgress Start the issue progress
stopProgress Stop the issue progress
reopen Reopen the issue
open Open the issue
resolve fixed Resolve the issue because it is fixed
resolve wontfix The issues can't be fixed (E.g.: An obsolete issue)
resolve duplicate Resolve the issue because it is duplicated
resolve incomplete Resolve the issue because of incomplete informations
resolve cantreproduce Resolve the issue because it is wasn't possible to reproduce it

That's it for today. You should now have Git and Jira integrated, and Gitolite managing your Git users. The next article will be about Bamboo and its integration to the other application and to Git.

If you have any question or if you want to share any improvement to the content of this article, post a comment or contact us. You liked this article and you want to receive the next articles on your RSS reader, subscribe to the RSS feed. You liked this article and you want to share it to your community? Use the share button on the footer. If you want to keep in touch with the Antelink team, you can follow the personalized Twitter list and the Antelink Twitter account.

Stay informed on our latest news!

Follow us