summaryrefslogtreecommitdiff
path: root/gitaccess
diff options
context:
space:
mode:
Diffstat (limited to 'gitaccess')
-rwxr-xr-xgitaccess173
1 files changed, 0 insertions, 173 deletions
diff --git a/gitaccess b/gitaccess
deleted file mode 100755
index 7c0a7fe..0000000
--- a/gitaccess
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/usr/bin/env bash
-#
-# Gitaccess implements basic access controls for git.
-# Copyright (C) 2017 Aaron Ball <nullspoon@oper.io>
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-#
-# Description
-# -----------
-#
-# This script provides basic access controls to git repos. For this script to
-# work, it requires that each repository has a 'users' file. This script reads
-# that file and determines if the user associated with the logged in ssh key
-# has access to that repo.
-#
-# This script also provides support for interactive git shell, interactive
-# shell rejection via the no-interactive-shell script, and any other scripts
-# that are placed inside the ~/git-shell-commands directory.
-#
-# To use this script for a specified ssh key, call it using the command
-# directive in the ~/.ssh/authorized keys file using the following syntax
-#
-# # Key for user <username>
-# command="gitaccess <username>" ecdsa-sha2-nistp521 AAAAE2v....
-#
-
-
-#
-# Logging function for standardized log output. This also ensures that log
-# messages don't cause perceived corruption in git responses, as they always
-# report to stderr.
-#
-# @param lvl Log level string. Can be anything, but error, info, warn, fatal,
-# etc. are recomended
-# @param msg Log message
-#
-log() {
- local lvl=${1}
- shift
- local msg=${@}
-
- d=$(date '+%F %T')
- printf "%s %s %s\n" "${d}" "${lvl}" "${msg[@]}" >> ~/git.log
- printf "%s %s %s\n" "${d}" "${lvl}" "${msg[@]}" >&2
-}
-
-# Some logging macros to save typing time and space
-lerror() { log 'error' ${@}; }
-linfo() { log 'info ' ${@}; }
-lwarn() { log 'warn ' ${@}; }
-lwarn() { log 'fatal' ${@}; }
-
-
-#
-# Resolves the specified git repo path. Returns failure if...
-# No repo exists at the path
-# No repo exists at the path with .git appended
-# The specified path exists, but is no a bare repository
-#
-# If the path is able to be resolved, the updated path is returned with an exit
-# code of 0.
-#
-# @param repopath Path to the repo to resolve
-#
-git_resolve_path() {
- local repopath=${1:-}
- local isbare
-
- # Resolve the path correctly if it has .git on the end that was not specified
- [ -d ${repopath}.git ] && repopath=${repopath}.git
- # If no repo can be found still, return failure
- [ ! -d ${repopath} ] && lerror "No repo exists at ${repopath}" && return 1
-
- isbare=$(git --git-dir="${repopath}" rev-parse --is-bare-repository 2>/dev/null)
- [ "${isbare:-}" = 'true' ] && printf ${repopath} && return 0
-
- lerror "Not a git repository: ${repopath}"
- return 1
-}
-
-
-#
-# Checks if the specified user has acccess to the specified repo.
-# Requires the presence of the users file at the top level of the bare repo.
-# This file should contain one username per line
-#
-# @param repopath Path to the repo we're checking access to
-# @param user Username to check for access
-#
-git_check_access() {
- local repopath=${1}
- local user=${2}
-
- local found=0 # Number of times the user is found in the users file
-
- if [ -d ${repopath} ]; then
- # Fail if users file is not found
- if [ ! -f ${repopath}/users ]; then
- lerror "No users file found in ${repopath}."
- lerror "Access denied"
- printf 0
- return 1
- fi
-
- # Check if the user is in the users file
- found=$(grep -c "^[ ]*${user}[ ]*$" ${repopath}/users)
- if [ ${found} -eq 0 ]; then
- lerror "Permission denied for ${user} to ${repopath}"
- printf 0
- else
- linfo "Permission granted for ${user} to ${repopath}"
- printf 1
- fi
- else
- lerror "Could not find repo at ${repopath}."
- return 3
- fi
-}
-
-
-#
-# Ye olde main
-#
-main() {
- local user="${1:-}"
-
- local repopath='none'
-
- # Detect if someone tries to launch this script from this script, thus creating
- # an infinite recursive loop spawning subshells.
- if [ "${SSH_ORIGINAL_COMMAND:-}" = "$(basename ${0})" ]; then
- log error "Blocking infinite recursion"
- exit 1
- fi
-
- # Launch git interractive shell if no commands were specified
- if [ -z "${SSH_ORIGINAL_COMMAND:-}" ]; then
- /usr/bin/env git shell
- return $?
- fi
-
- # If the user specified a git-* command, check if they have access to run it.
- if [ "${SSH_ORIGINAL_COMMAND:0:4}" = 'git-' ]; then
- # Parse the repo path out from the git command
- repopath="$(echo ${SSH_ORIGINAL_COMMAND} | cut -d ' ' -f 2 | tr -d "'")"
-
- # Resolve the repo path (in case it needs a .git or something else)
- repopath=$(git_resolve_path "${repopath}")
- [ $? -gt 0 ] && return 1
-
- # Verify the user has access to this repo
- allowed=$(git_check_access "${repopath}" "${user}")
- [ ${allowed} -ne 1 ] && exit 1
- fi
-
- # All checks passed. Run the command
- /usr/bin/env git shell -c "${SSH_ORIGINAL_COMMAND}"
-}
-
-main ${@}

Generated by cgit