git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Carl Baldwin <cnb@fc.hp.com>
To: Junio C Hamano <junkio@cox.net>, git@vger.kernel.org
Subject: Re: [RFC] Using sticky directories to control access to branches.
Date: Thu, 1 Dec 2005 08:42:22 -0700	[thread overview]
Message-ID: <20051201154222.GB18993@hpsvcnb.fc.hp.com> (raw)
In-Reply-To: <20051121180133.GA28171@hpsvcnb.fc.hp.com>

I have tweaked the script a little.  I thought I'd send to the list in
case anyone was following this.  If not, then safely ignore this.

#!/bin/bash

umask 002

# If you are having trouble with this access control hook script you can try
# setting this to true.  It will tell you exactly why a user is being
# allowed/denied access.
verbose=false

# Default shell globbing messes things up downstream
GLOBIGNORE=*

function grant {
  $verbose && echo >&2 "-Grant-		$1"
  echo grant
  exit 0
}

function deny {
  $verbose && echo >&2 "-Deny-		$1"
  echo deny
  exit 1
}

function info {
  $verbose && echo >&2 "-Info-		$1"
}

# Implement generic branch and tag policies.
# - Tags should not be updated once created.
# - Branches should only be fast-forwarded.
case "$1" in
  refs/tags/*)
    [ -f "$GIT_DIR/$1" ] && deny >/dev/null "You can't overwrite an existing tag"
    ;;
  refs/heads/*)
    # No rebasing or rewinding
    if expr "$2" : '0*$' >/dev/null; then
      info "The branch '$1' is new..."
    else
      # updating -- make sure it is a fast forward
      mb=$(git-merge-base "$2" "$3")
      case "$mb,$2" in
        "$2,$mb") info "Update is fast-forward" ;;
        *)        deny >/dev/null  "This is not a fast-forward update." ;;
      esac
    fi
    ;;
  *)
    deny >/dev/null "Branch is not under refs/heads or refs/tags.  What are you trying to do?"
    ;;
esac

# Implement per-branch controls based on username
allowed_users_file=$GIT_DIR/info/allowed-users
username=$(id -u -n)
info "The user is: '$username'"

if [ -f "$allowed_users_file" ]; then
  rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
    while read head_pattern user_patterns; do
      matchlen=$(expr "$1" : "$head_pattern")
      if [ "$matchlen" == "${#1}" ]; then
        info "Found matching head pattern: '$head_pattern'"
        for user_pattern in $user_patterns; do
          info "Checking user: '$username' against pattern: '$user_pattern'"
          matchlen=$(expr "$username" : "$user_pattern")
          if [ "$matchlen" == "${#username}" ]; then
            grant "Allowing user: '$username' with pattern: '$user_pattern'"
          fi
        done
        deny "The user is not in the access list for this branch"
      fi
    done
  )
  case "$rc" in
    grant) grant >/dev/null "Granting access based on $allowed_users_file" ;;
    deny)  deny  >/dev/null "Denying  access based on $allowed_users_file" ;;
    *) ;;
  esac
fi

allowed_groups_file=$GIT_DIR/info/allowed-groups
groups=$(id -G -n)
info "The user belongs to the following groups:"
info "'$groups'"

if [ -f "$allowed_groups_file" ]; then
  rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
    while read head_pattern group_patterns; do
      matchlen=$(expr "$1" : "$head_pattern")
      if [ "$matchlen" == "${#1}" ]; then
        info "Found matching head pattern: '$head_pattern'"
        for group_pattern in $group_patterns; do
          for groupname in $groups; do
            info "Checking group: '$groupname' against pattern: '$group_pattern'"
            matchlen=$(expr "$groupname" : "$group_pattern")
            if [ "$matchlen" == "${#groupname}" ]; then
              grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
            fi
          done
        done
        deny "None of the user's groups are in the access list for this branch"
      fi
    done
  )
  case "$rc" in
    grant) grant >/dev/null "Granting access based on $allowed_groups_file" ;;
    deny)  deny  >/dev/null "Denying  access based on $allowed_groups_file" ;;
    *) ;;
  esac
fi

deny >/dev/null "There are no more rules to check.  Denying access"
On Mon, Nov 21, 2005 at 11:01:33AM -0700, Carl Baldwin wrote:
> OK,
> 
> To follow-up on this.  Here is a final version of this script that was
> started by Junio.  I polished it and made it work the way I want it.
> Hopefully, someone on the list will find it useful.
> 
> Here is a basic description.  There are two files:
> .git/info/allowed-users
> .git/info/allowed-groups
> 
> The users file is checked, line by line, followed by the groups file.
> The first line matching the ref to be updated is used.  Each line has
> one regular expression to match the ref followed by one or more regular
> expressions to match user (or group).  Space is the delimeter so the RE
> cannot contain a space.
> 
> If no line matches the ref then access is denied.  For this reason I
> tend to include the following line as the last line of allowed-groups as
> the default since it will match any ref and any group.
> 
> .* .*
> 
> Here is the hook script...  Thanks to Junio for getting me started.  I
> rewrote the whole thing using my own style but much of the code is based
> on his.
> 
> #!/bin/bash
> 
> umask 002
> 
> verbose=no
> 
> # Default shell globbing messes things up later
> GLOBIGNORE=*
> 
> function grant {
>   [ "yes" == "$verbose" ] && echo >&2 "-Grant-		$1"
>   exit 0
> }
> 
> function deny {
>   [ "yes" == "$verbose" ] && echo >&2 "-Deny-		$1"
>   exit 1
> }
> 
> function info {
>   [ "yes" == "$verbose" ] && echo >&2 "-Info-		$1"
> }
> 
> # Implement generic branch and tag policies.
> # - Tags should not be updated once created.
> # - Branches should only be fast-forwarded.
> case "$1" in
>   refs/tags/*)
>     [ -f "$GIT_DIR/$1" ] && deny "You can't overwrite an existing tag"
>     ;;
>   refs/heads/*)
>     # No rebasing or rewinding
>     if expr "$2" : '0*$' >/dev/null; then
>       info "The branch '$1' is new..."
>     else
>       # updating -- make sure it is a fast forward
>       mb=$(git-merge-base "$2" "$3")
>       case "$mb,$2" in
>         "$2,$mb") info "Update is fast-forward" ;;
>         *)        deny  "This is not a fast-forward update." ;;
>       esac
>     fi
>     ;;
>   *)
>     deny "Branch is not under refs/heads or refs/tags.  What are you trying to do?"
>     ;;
> esac
> 
> # Implement per-branch controls based on username
> allowed_users_file=$GIT_DIR/info/allowed-users
> username=$(id -u -n)
> info "The user is: '$username'"
> 
> if [ -f "$allowed_users_file" ]; then
>   3<$allowed_users_file
>   while read -u 3 head_pattern user_patterns; do
>     matchlen=$(expr "$1" : "$head_pattern")
>     if [ "$matchlen" == "${#1}" ]; then
>       info "Found matching head pattern: '$head_pattern'"
>       for user_pattern in $user_patterns; do
>         info "Checking user: '$username' against pattern: '$user_pattern'"
>         matchlen=$(expr "$username" : "$user_pattern")
>         if [ "$matchlen" == "${#username}" ]; then
>           grant "Allowing user: '$username' with pattern: '$user_pattern'"
>         fi
>       done
>       deny "The user is not in the access list for this branch"
>     fi
>   done
> fi
> 
> allowed_groups_file=$GIT_DIR/info/allowed-groups
> groups=$(id -G -n)
> info "The user belongs to the following groups:"
> info "'$groups'"
> 
> if [ -f "$allowed_groups_file" ]; then
>   4<$allowed_groups_file
>   while read -u 4 head_pattern group_patterns; do
>     matchlen=$(expr "$1" : "$head_pattern")
>     if [ "$matchlen" == "${#1}" ]; then
>       info "Found matching head pattern: '$head_pattern'"
>       for group_pattern in $group_patterns; do
>         for groupname in $groups; do
>           info "Checking group: '$groupname' against pattern: '$group_pattern'"
>           matchlen=$(expr "$groupname" : "$group_pattern")
>           if [ "$matchlen" == "${#groupname}" ]; then
>             grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
>           fi
>         done
>       done
>       deny "None of the user's groups are in the access list for this branch"
>     fi
>   done
> fi
> 
> deny "There are no more rules to check.  Denying access"
> # End script here
> 
> Carl
> 
> -- 
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>  Carl Baldwin                        Systems VLSI Laboratory
>  Hewlett Packard Company
>  MS 88                               work: 970 898-1523
>  3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com
>  Fort Collins, CO 80525              home: Carl@ecBaldwin.net
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> -
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Carl Baldwin                        Systems VLSI Laboratory
 Hewlett Packard Company
 MS 88                               work: 970 898-1523
 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com
 Fort Collins, CO 80525              home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  parent reply	other threads:[~2005-12-01 15:42 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-17 17:01 [RFC] Using sticky directories to control access to branches Carl Baldwin
2005-11-18  7:55 ` Junio C Hamano
2005-11-21 18:01   ` Carl Baldwin
2005-11-21 19:29     ` Junio C Hamano
2005-12-01 15:42     ` Carl Baldwin [this message]
2005-12-02  1:13       ` Junio C Hamano
2005-12-02  9:29         ` Andreas Ericsson
2005-12-02  9:35           ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20051201154222.GB18993@hpsvcnb.fc.hp.com \
    --to=cnb@fc.hp.com \
    --cc=git@vger.kernel.org \
    --cc=junkio@cox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).