Exercises in Restful Integration and Continuous Delivery

Musing on Software Development and Technologies.

Sat 01 December 2018

Git Repo in Shared Hosting #2 - Code Review

Posted by Mikko Koivunalho in How-To   

Review Board Logo

In this series of four articles we show how to share a Git repository via a Linux shell account and a shared hosting Apache HTTP server without root access.

In the first article we will learned how we can share our Git repository with others securily and yet allow them to commit (push) to the repo.

In the second article we will now set up the web-based collaborative code review tool Review Board to work with our repository and make it accessible for users via our homepage. Review Board can be used for any text document review - not just code review - and is very convenient although not easy to set up. Review Board is under MIT license and free to use.

In the third article we will make our repository even more secure and usable with the help of a Git hooks framework, the Perl based Git::Hooks

In the fourth article we will use SSH connection and SSH public keys to give access and also limit access to our repositories.

Prerequisites

  • Shell account on a Linux server. All shell commands are executed in bash.
  • Apache HTTP server with distributed configuration allowed.
  • Git.
  • Python with Virtualenv configured.
  • The need to work collaboratively! Need is the greatest innovator.
  • The repositories we set up in the previous article.

Code And Other Reviews With Review Board

Review Board is a versatile code review tool. Or, more precisely, a tool to review any text based document. It even supports reviewing images. It can be used to work collaboratively in almost any project. It is also completely free to use and it is open source. (It does allow additional extensions for which one might need to pay but there is nothing missing from the free part of Review Board.)

We are going to install and setup the Review Board in an Apache HTTP server without root access. We are using the .htaccess files to configure server and protect our Review Board by limiting access to it. Then we will configure the Review Board itself to work with the shared repository in ${HOME}/repos/shared/shared-repo.git accessible via HTTP endpoint https://@/repos/shared/shared-repo.git

Installation Instructions And Omissions

Review Board is programmed with Python and built using the Django web application framework. This makes the installation flexible because Django itself is flexible in how it speaks with the web server. There are two ways to run Review Board: in its own process as a standalone service which is accessed via web server (so it gets an HTTP endpoint within the web site), or it can be started up by the web server whenever someone actually uses it. The first method is the preferred method of using Review Board in production because it is faster. The second method however does not require root access.

Review Board official installation instructions for Linux say that Review Board requires "Apache + mod_wsgi". They also state that "The instructions below are assuming you’re logged in as root or are using sudo.. If your Apache HTTP is running mod_wsgi you most likely have root access or otherwise command over the whole server. The module mod_wsgi uses the Python WSGI standard to interface the supporting program which can be either a constant running service or started when called. However, to achieve the faster speed, mod_wsgi runs all programs in the same process. This is inherently insecure so shared hosting sites normally do not allow this!

So we will instead use FastCGI standard which is equally supported by Django and often the only option (except for CGI) in shared hosting.

Please consult Review Board installation instructions on what else you need or might want, for example SSH libraries and database (MySQL or PostgreSQL - unless you use SQLite). For this article we assume SQLite and no Memcache.

Prepare For Installation

Create a directory to house all that stuff we need but need not and want not put under web server. This just for security's sake, like in the previous article the actual Git repositories are located in home directory and web server only contains scripts to access them. However, this directory must be visible to Apache HTTP daemon! Please see What is my Path? for a way to see which directories are visible. Be certain of this directory, especially because we later install a virtual Python environment and once it is in place, it is impossible to move but has to be instead remade in the new location.

Create a variable to use later to reference the directory. Here we assume that user home directory is visible to the web server!!! If you followed the previous tutorial, I recommend you use the same directory as with the Git repositories, e.g. ${HOME}/reviewboard

export REVIEWBOARD_PATH="<FULL PATH HERE>"
mkdir -p ${REVIEWBOARD_PATH}

On To Python!

Review Board is a Python program and very easy to install with normal Python tools. We do not want to pollute the system's (or user's) global Python module space so we will instead create a Python virtual environment with Virtualenv tool. If you haven't got command virtualenv installed, install instead pyenv, Python version manager and use its pyenv-virtualenv plugin. Or install anyenv, environment manager which will then easily install pyenv. To continue, you need the command virtualenv in your path.

Review Board requires Python 2.7. So you need that as well. Most if not all Linux distributions have Python 2.7 preconfigured. In case you do not have it, use pyenv to install it and activate it.

N.B. I have had problems with Python 2.7.10 and 2.7.15, so I stick with Python 2.7.9 which is working. I have also had problems with virtualenv version 16.*. Older version 1.11.6 is working for me.

pyenv install 2.7.9

Create environment with virtualenv.

virtualenv --always-copy ${REVIEWBOARD_PATH}/venv

Again, if you don't have Virtualenv installed (in Python 2), use pyenv:

pyenv shell 2.7.9
pip install virtualenv
virtualenv --always-copy ${REVIEWBOARD_PATH}/venv
pyenv shell --unset

ATTN. Do not use pyenv plugin pyenv-virtualenv! It creates a virtual environment in a subdirectory under its own install directory, not where we want!

Update the virtual environment and install extra stuff. We need an older version of flup because newer versions only support Python 3.

N.B. From this point onwards we always call Python or Pip using their full path to avoid by mistake calling the system Python.

${REVIEWBOARD_PATH}/venv/bin/pip install -U pip setuptools
${REVIEWBOARD_PATH}/venv/bin/pip install flup==1.0.3.dev-20110405
${REVIEWBOARD_PATH}/venv/bin/pip install reviewboard

Review Board Configuration

Follow instruction in Creating a Review Board Site! Skip the database preparations if you use SQLite.

Begin site creation. Set environmental variable REVIEWBOARD_HTTP to the directory on the web server. Last directory on the path must be called reviewboard, e.g. ${HOME}/public_html/reviewboard. Change the \<DOMAIN> to your domain name, e.g. my.domain.org. Change admin-user, admin-password and admin-email to what you need!

export REVIEWBOARD_HTTP="<FULL PATH HERE>"
mkdir -p ${REVIEWBOARD_HTTP}
export REVIEWBOARD_DOMAIN="<DOMAIN>"
${REVIEWBOARD_PATH}/venv/bin/rb-site install --advanced --copy-media \
--noinput --domain-name="${REVIEWBOARD_DOMAIN}" --site-root="/reviewboard/" \
--db-type="sqlite3" --db-name=${REVIEWBOARD_PATH}/data.db \
--cache-type="file" --cache-info="${REVIEWBOARD_PATH}/cache" \
--web-server-type="apache" --python-loader="fastcgi" \
--admin-user="admin" --admin-password="admin" --admin-email="admin@${REVIEWBOARD_DOMAIN}" \
${REVIEWBOARD_HTTP}

We have created the Review Board site. You can now take a look at the site configuration file ${REVIEWBOARD_HTTP}/conf/settings_local.py.

If you believe you need extra logging information, execute the following to mend the configuration:

sed --in-place 's/DEBUG = False/DEBUG = True/' ${REVIEWBOARD_HTTP}/conf/settings_local.py
cat >>${REVIEWBOARD_HTTP}/conf/settings_local.py <<EOF

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '${REVIEWBOARD_PATH}/debug.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

EOF

Apache configuration

Take a look at the file ${REVIEWBOARD_HTTP}/htdocs/reviewboard.fcgi! The shebang row (top row) contains "#!/usr/bin/env python". Replace this with the absolute path of the virtual environment Python binary.

sed --in-place "1 s/^.*$/\#\!${REVIEWBOARD_PATH//\//\\/}\/venv\/bin\/python/" ${REVIEWBOARD_HTTP}/htdocs/reviewboard.fcgi

There are other paths which might also be wrong: sys.path.insert, PYTHON_EGG_CACHE and HOME. Correct these so that the absolute path is the one which is also visible to the web server, if your homedir is not. If you set the correct absolute path to variable REVIEWBOARD_HTTP, then these should be correct already.

Command rb-site created a site configuration file ${REVIEWBOARD_HTTP}/conf/apache-fastcgi.conf for Apache HTTP. This file is useless for us since we are using Apache HTTP distributed configuration (.htaccess files).

Create the .htaccess file.

cat > ${REVIEWBOARD_HTTP}/.htaccess <<EOF
# Activate FastCGI in Apache. Only files with ending ".fcgi".
AddHandler fcgid-script .fcgi

# Prevent all access to directories
Options -Indexes

# Force HTTPS
RewriteEngine On
RewriteCond %{ENV:HTTPS} !on
RewriteRule (.*) https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Error handlers
ErrorDocument 500 /reviewboard/errordocs/500.html

# Document paths
RewriteRule ^(media.*)\$ htdocs/\$1 [QSA,L,PT]
RewriteRule ^(static.*)\$ htdocs/\$1 [QSA,L,PT]
RewriteRule ^(errordocs.*)\$ htdocs/\$1 [QSA,L,PT]

# Executable Path
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\$ htdocs/reviewboard.fcgi/reviewboard/\$1 [QSA,E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

# Ensure Strict-Transport-Secure
Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"

EOF

A word about security: You can do two things: 1) Protect the directory with Basic HTTP Authentication (forcing users to log in) 2) You can limit the allowed IP addresses.

Please see the previous article for examples on these. Remember that Review Board has its own security and requires users to log in. Apache HTTP Server security and Review Board security complement each other.

If you have no other security, you can allow all traffic and let Review Board handle access.

cat >> ${REVIEWBOARD_HTTP}/.htaccess <<EOF

# Allow all! Tighten security if you know the IP addresses of your visitors.
<Limit GET POST PUT DELETE OPTIONS PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
  order deny,allow
  allow from all
</Limit>

EOF

Or you can create only one Basic HTTP Authentication user for all trusted people. That user could be called visitor. Follow instructions in Private Repository Part 1.

Emergency Password Reset

If you didn't set the admin user password when creating the site, or have just forgotten it, create a new superuser with this command and use it to reset admin user's password and then remove the temporary user.

${REVIEWBOARD_PATH}/venv/bin/rb-site manage ${REVIEWBOARD_HTTP} createsuperuser

Configure Review Board to use Our Repositories

Now is time to log in to our Review Board installation as admin and start configuring it! The first time to access it will take longer because there is much code (Django framework and Review Board) to load and process. But all queries afterwards will be faster because FastCGI keeps the process alive. It does not need to be started again at every query.

Review Board Admin Dashboard - The configuration changes we need to make.

Start with Authentication. Since this is a standalone very private Review Board, select Standard Registration as Authentication Method. Decide if you want to let the users themselves register into your Review Board or if you want to create the users as needed. For users who sign in by themselves, Review Board even can use a captcha service.

The user (1.) and review group (2.) settings depend on your previous choice on how users sign in, so I am not going deeper into them.

If you didn't allow free sign in for the reviewers, you need to add the users individually.

Add two review groups.

First: Name: shared-repo-reviewers, Display name: Shared Repository Reviewers. Second: Name: public-repo-reviewers, Display name: Public Repository Reviewers.

Make the group Invite only and select the users or let the users themselves select the membership.

Now (3.) we will connect our previously created shared-repo.git and public-repo.git repositories to Review Board. There are two ways: either by file or by HTTP.

Review Board Admin Dashboard - Add repository.

We will use the local file system access. Again we need the absolute path to the repository, the one defined with variable REPOS_PATH in the previous article. So path would be \<FULL REPOS_PATH\>/repos/shared/shared-repo.git.

Verify

Go to the working checked out shared-repo.git you made in the previous article.

Open the list of all repositories in Review Board Admin Dashboard and follow the instructions under link RBTools Setup.

Review Board Admin Dashboard - Repositories.

You can either use RBTools' rbt command or you can take a diff with git, save it to a file and upload that file to Review Board.

Working Without RBTools

Create a file, for example the .reviewboardrc file mentioned above, and commit it without pushing.

git add .reviewboardrc
git commit -m "Add file .reviewboardrc"

Get diff.

git diff --no-color --full-index --ignore-submodules -M --no-ext-diff HEAD~1

Working With RBTools

You need to install RBTools. You can use pyenv to create a new Python virtual environment and install RBTools there. You maybe already have Python 2.7.15. RBTools are only used in interactive shell sessions, so we can now use pyenv virtualenv which we cannot use via HTTP server.

pyenv virtualenv 2.7.15 rbtools
pyenv shell rbtools
pip install rbtools

git add .reviewboardrc
git commit -m "Add file .reviewboardrc"
rbtools post HEAD~1

Ready! Congratulations!


    
 
 

Comments