-Build
------
+= About repo_shell
-make repo_shell
+repo_shell provides a login shell simplifying hosting of centralized subversion
+and git repositories. Repositories are accessed via SSH as the requesting
+user. SSH key authentication is activated when a user adds their SSH private
+key to their ~username:.ssh/authorized_keys file on the server.
-Install
--------
+repo_shell supports authorization on a per user and per repository basis. For
+git, repo_shell authorizes using an internal algorithm against a server-wide git
+acl file. For subversion, repo_shell leverages the already existing path based
+access control functionality.
-sudo cp repo_shell /usr/local/bin/
+To increase integrity of the repositories and to simplify filesystem
+permissions, repo_shell expects all repository files to be owned by a single,
+configurable system user. Users cannot access repository files directly on the
+server, only using the git or subversion client side tools.
-Configure
----------
+= Acquire, build and install
-cat <+EOF+ > repo_shell.cfg
-[core]
-owner=repo
-git_root=/var/lib/git
-svn_root=/var/lib/svn/repositories
-+EOF+
-sudo mv repo_shell.cfg /etc/
+ git clone git://oss.titaniummirror.com/repo_shell.git
+ cd repo_shell
+ make
+ sudo make install
-Notes
------
-The inih library comes from:
-URL: http://inih.googlecode.com/svn/trunk
-Repository Root: http://inih.googlecode.com/svn
-Repository UUID: f5d6dc10-6d35-11de-b131-07d8e4d3762e
-Revision: 22
+Please build from a repository clone, as the make script uses
+'git describe --tags' to generate the resulting executable's version string.
+= Configure /etc/repo_shell.conf
+
+The file /etc/repo_shell.conf must contain certain fields as shown in the
+example below. The spaces surrounding the equal sign ('=') are optional.
+
+ owner = repo
+ svn_root = /var/lib/svn/repositories
+ git_root = /var/lib/git
+ allowed_interactive =
+
+owner is the system account username which will own all repositories, and is
+preferaby a system account used for no other purpose. Use the adduser or
+another similar system script to assist in creating the user account. The
+account home directory can be one of the repository root paths
+
+svn_root and git_root are self-explanatory, being the longest filesystem path
+shared by repositories of that type, e.g. their shared root directory.
+
+allow_interactive contains a list of users that may log into the server via SSH,
+or that may issue arbitrary commands to the server via SSH. Instead of a list,
+the wildcard character '*' can be used to indicate all users. Note that this
+only affects users that have /usr/local/bin/repo_shell as their login shell.
+If the server is only hosting repositories, there is no reason for users to be
+allowed 'interactive' access.
+
+== allowed_interactive and sudo ==
+
+For users that use repo_shell as a login shell and that also need to run
+commands via sudo as other users, those other users must also be listed in the
+allowed_interactive user list. Otherwise, sudo functionality is effectively
+disabled for such users.
+
+= Create owner and paths
+
+In accordance with the settings in /etc/repo_shell.conf:
+
+ sudo adduser --system --group --home /var/lib/svn --shell /bin/false <owner>
+ sudo chsh -s /bin/bash <owner> # a shell is needed for 'sudo -iu'
+ sudo install -d -o <owner> -g <owner> -m 0750 <svn_root>/..
+ sudo install -d -o <owner> -g <owner> -m 0750 <svn_root>
+ sudo install -d -o <owner> -g <owner> -m 0750 <git_root>
+
+= Configure subversion repository ACLs
+
+Subversion repositories created with the svncreate command have their
+conf/svnserve.conf as a symbolic link pointing to the global
+{svn_root}/../svnserve.conf file, which then references internally the global
+authz.conf file. It is this file that is used to set access control permissions
+for repositories. Subversion's authz file allows path based control as well.
+For more information, please see the Subversion Red Bean guide at:
+http://svnbook.red-bean.com/en/1.7/svn.serverconfig.pathbasedauthz.html
+
+A simple and secure svnserve.conf file:
+
+ [general]
+ anon-access = none
+ auth-access = write
+ authz-db = /var/lib/svn/authz.conf
+
+A simple and secure authz.conf file:
+
+ [groups]
+ devs = user1, user2, user3
+
+ [/] # All repositories, all paths
+ @devs = rw
+ * =
+
+For path-based controls, consider using the pre-commit hook that uses
+svnperms.py. The ability to prevent update of tags, which my definition is
+almost always an accident, is itself worth the price of admission.
+
+= Configure git repository ACLs
+
+Git repository access control is managed by the git acl file, located at
+{git_root}/.gitacls (git_root is defined in /etc/repo_shell.conf). This file
+has a format similar but not exactly like Subversion's authz file. The file
+defines one of three levels of access for various combinations of users and
+repositories, then compared to the git command arriving via SSH to determine if
+the access will be allowed. Please see README.gitacls for more information.
+A simple .gitacls might look like:
+
+ [user_groups]
+ devs = user1 user2 user3
+
+ [repo *]
+ devs = rw
+ * =
+
+= Create a subversion repository
+
+svncreate is a helper script installed by make install. To create a new
+subversion repository, simply type:
+
+ sudo -u repo svncreate <reponame>
+
+The script creates an fsfs type repository with proper permissions, and
+referencing the {svn_root}/../authz.conf file for access control. Edit this
+file as necesssary to allow access to the new repository.
+
+= Create a git repository
+
+gitcreate is a helper script installed by make install. To create a new git
+repository, simply type:
+
+ sudo -u repo gitcreate <repopath> ["Short description"]
+
+Git repositories may be placed in subdirectories under {git_root}. A
+subdirectory may be part of <repopath>. So, for example, if one wishes to
+create a repository tinyos-main.git under a subdirectory mirrors/tinyos, then
+the create command would be:
+
+ sudo -u repo gitcreate mirrors/tinyos/tinyos-main.git
+
+If a subdirectory path being requested doesn't already exist, the script will
+ask the operator if it is OK to create it. To automatically create non-existent
+subdirectory paths, add the -y option:
+
+ sudo -u repo gitcreate -y mirrors/tinyos/tinyos-main.git
+
+If the optional extra argument is provided, it will be used to populate the
+description file of the new repository. Because the script takes only one
+argument for this purpose, enclose the description in double quotes.
+
+= Configuring user accounts
+
+Each user to access repositories via client side tools need an account on the
+server. This was a purposeful design decision to allow password authentication
+as well as key authentication via SSH. Accounts for repository users must have
+/usr/local/bin/repo_shell set as their shell.
+
+To create a new user:
+
+ sudo adduser --shell /usr/local/bin/repo_shell <newuser>
+
+To allow an existing user access to repositories via client-side tools:
+
+ sudo chsh -s /usr/local/bin/repo_shell <existinguser>
+
+To completely disable repository access for an existing user, return their shell
+to /bin/bash:
+
+ sudo chsh -s /bin/bash <existinguser>
+
+or, instead, ensure their access permissions to repositories is set to none for
+both subversion and git repositories.
+
+= Access paths for client side access
+
+Users interact with subversion and git repositories using what we somewhat
+incorrectly call access paths. In both cases, the access path is relative to
+the respective repository type root, as defined in /etc/repo_shell.conf. In
+other words, the user does not need to know where the repository is stored. In
+the case of git, a repository can be under a subdirectory. A couple of
+examples:
+
+ svn checkout svn+ssh://server/my_repository/trunk my_repository
+ git clone server:my_repository.git
+ git clone server:mirrors/tinyos/tinyos-main.git
+
+= Repository access for gitweb
+
+The following steps can allow gitweb to filter the available repositories
+according to the authenticated user and the contents of the .gitacl file.
+
+- The web server must require authorization and a valid user for URI's starting
+ with /gitweb. Recommend using a PAM module, since repo_shell also works of
+ the system user credentials.
+- The web server needs to pass the REMOTE_USER environment variable to
+ gitweb.cgi.
+- The contents of the file gitweb.conf.addon must be added to the server's
+ gitweb.conf file, usually found in /etc.
+
+The contents of gitweb.conf.addon essentially define an $export_auth_hook that
+uses repo_shell's test mode to validate read access for the web server
+authenticated user for each repository gitweb can see.
+
+= Repository access for other applications
+
+Local system applications, such as web based viewers, may gain read-only access
+to repositories by adding the user which runs such a tool to the repository
+owner's group. However, such an access method bypasses access control
+functionality and all repositories will be viewable by the application.
+
+A better solution, requiring some scripting work, would be to have the other
+application use output from the repo_shell -c command to determine access.
+
+ repo_shell -c <username> <reponame>
+
+This command returns one of three results. An empty return string means no
+access, an "r" means read-only, and "rw" means read-write access.
+
+= Allow other users to create repositories
+
+With the following configuration, other users could be configured to run the
+`gitcreate` command using sudo.
+
+First, run `visudo` as root to edit the `/etc/sudoers` file. These entries
+should appear before less specific rules. The Runas_Alias REPOUSER should be
+set to the value of the `owner` variable defined in `/etc/repo_shell.conf`.
+
+ # Allow select users to run gitcreate
+ User_Alias REPOCREATORS = user1, user2, user3
+ Runas_Alias REPOUSER = repo
+ REPOCREATORS ALL = (REPOUSER) NOPASSWD: /usr/local/bin/gitcreate
+
+Now any users listed in the User_Alias REPOCREATORS can run the gitcreate
+command. The command would be invoked as follows:
+
+ ssh <repohost>
+ sudo -u repo gitcreate path/to/newrepo.git
+
+Note that as of right now, repo_shell cannot be used to run this command in a
+single ssh invocation, such as:
+
+ ssh <repohost> sudo gitcreate path/to/newrepo.git
+
+This is because repo_shell does not implement a full tty needed by sudo if it
+must ask the user for a password to authenticate the action.
+
+= References and links
+
+repo_shell owes great thanks to work shared by two other projects:
+
+- The GIT stupid content tracker - http://git-scm.org
+ Some useful information was gleaned from git's git-shell program.
+ GIT is licensed under the GPLv2.
+
+- The inih .ini parser library - http://code.google.com/p/inih/
+ This is a great little library for handling simple configuration files.
+ inih is licensed under a modified BSD license, available in inih/LICENSE.txt.
+
+- Subversion's authz file
+ http://svnbook.red-bean.com/en/1.7/svn.serverconfig.pathbasedauthz.html