diff options
Diffstat (limited to 'gitaccess')
-rwxr-xr-x | gitaccess | 173 |
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 ${@} |