Re: [RFC] Using sticky directories to control access to branches.
- From
- Carl Baldwin <cnb@fc.hp.com>
- Date
- Dec 1, 2005, 15:42 UTC
- Message-ID
- <20051201154222.GB18993@hpsvcnb.fc.hp.com>
- 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
fiallowed_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
fideny >/dev/null "There are no more rules to check. Denying access" On Mon, Nov 21, 2005 at 11:01:33AM -0700, Carl Baldwin wrote:
Show 140 quoted lines
> 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -