= About 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. 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. 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. = Acquire, build and install git clone git://oss.titaniummirror.com/repo_shell.git cd repo_shell make sudo make install 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 sudo chsh -s /bin/bash # a shell is needed for 'sudo -iu' sudo install -d -o -g -m 0750 /.. sudo install -d -o -g -m 0750 sudo install -d -o -g -m 0750 = 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 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 ["Short description"] Git repositories may be placed in subdirectories under {git_root}. A subdirectory may be part of . 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 To allow an existing user access to repositories via client-side tools: sudo chsh -s /usr/local/bin/repo_shell To completely disable repository access for an existing user, return their shell to /bin/bash: sudo chsh -s /bin/bash 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 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 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 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