Table of Contents

About

Quite frequently on Linux the traditional permission system gets in the way of development due to file and directory permissions being crucial to the operation of software. Suppose that a directory is mounted over the network that should be accessed by multiple users yet that directory also contains configuration files that are being read by a system daemon. In such cases, the use of the sticky bit can come in handy to ensure that newly created directories and files are created under the system daemon's user and group permissions but this solution does not scale up when multiple users and groups are involved.

The script presented in this article leverages ACL permissions in order to provide a tool that can be used to grant a user and a group permissions to a directory. The script takes care to define default ACLs based on the existing unix permissions and then adds permission for the specified user and group.

Installing

To setup the script, create a file at /etc/default/systemize with the following contents:

# Parameters for the systemize command.
 
# Remove previous ACLs before granting (default: yes).
RESET_ACL_ENTRIES=yes
 
# The default user to grant permissions to (default: system).
GRANT_USR=administrator
 
# The default group to grant permissions to (default: system).
GRANT_GRP=administrator

Additionally, make sure that the user and group defined by GRANT_USR, respectively GRANT_GRP are valid users.

Then, create a file at /usr/local/bin/systemize with the contents from the code section. Finally, grant permission for the script to be executed:

chmod ug+x /usr/local/bin/systemize

Usage

Without further ado, to grant additional ACL permissions to the user and group defined in /etc/default/systemize, issue:

systemize DIRECTORY

where:

The systemize script also supports specifying the user or group (or both) on the command line - in case the user and group is specified on the command line, then it takes precedence over the user and group defined in /usr/local/bin/systemize. The invocation:

systemize -u office DIRECTORY

will:

Furthermore, systemize can also revoke permissions by using the action flag (-a) with the option set to either grant (default) or revoke. The invocation:

systemize -a revoke -u office DIRECTORY

will:

Code

systemize
#!/bin/sh
###########################################################################
##  Copyright (C) Wizardry and Steamworks 2018 - License: GNU GPLv3      ##
##  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  ##
##  rights of fair usage, the disclaimer and warranty conditions.        ##
###########################################################################
# Set ACL permissions on a directory for a specific user and group.       #
###########################################################################
 
# Load system defaults.
SCRIPT_NAME=`basename $0`
[ -f "/etc/default/$SCRIPT_NAME" ] && . /etc/default/"$SCRIPT_NAME"
 
# Check whether at least a directory was supplied.
if [ "$#" -lt 1 ] ; then
    echo "Syntax: $0 [-a <ACTION>][-u <USER>] [-g <GROUP>] <DIRECTORY>"
    exit 1
fi
 
while getopts "hu:g:a:" opt; do
    case "$opt" in
        u )
            GRANT_USR="$OPTARG"
            ;;
        g )
            GRANT_GRP="$OPTARG"
            ;;
        a )
            ACTION="$OPTARG"
            ;;
        * )
            echo "Syntax: $0 [-u <USER>] [-g <GROUP>] <DIRECTORY>"
            echo "Usage:"
            echo "    $SCRIPT_NAME                Display this help message."
            echo "    $SCRIPT_NAME <directory>    Set ACL on directory."
            echo ""
            echo "Options:"
            echo "    -a action    Revoke or grant (default: grant)."
            echo "    -u user      Set ACLs for user."
            echo "    -u group     Set ACLs for group."
            exit 0
            ;;
    esac
done
shift $((OPTIND-1))
 
if [ -z "$@" ] || [ ! -d "$@" ] ; then
    echo "Directory \"$@\" not found!"
    exit 1
fi
DIR="$@"
 
# Acquire a lock for the directory.
mkdir -p "/var/lock/$SCRIPT_NAME"
LOCK_FILE="/var/lock/$SCRIPT_NAME/$DIR"
while [ `mkdir "$LOCK_FILE"` ] ; do
    sleep 1
done
trap '{ rm -rf "$LOCK_FILE"; }' KILL QUIT TERM EXIT INT HUP
 
# Get the unix user and group.
USR=`stat --format "%U" "$DIR"`
GRP=`stat --format "%G" "$DIR"`
# Get the unix permissions.
set -- `stat -c "%A" /etc/openhab2 | \
    cut -c 2- | \
    sed -r 's/(.{3})/\1 /g' | \
    sed 's/\-//g'`
 
DIR_USR_PRM=$1
DIR_GRP_PRM=$2
DIR_OTR_PRM=$3
 
# Check that the grant user and group exist.
id "$GRANT_USR" 2>/dev/null >/dev/null
if [ "$?" -eq 1 ] || [ -z "$GRANT_USR" ] ; then
    echo "Grant user \"$GRANT_USR\" does not exist!"
    exit 1
fi
 
id "$GRANT_GRP" 2>/dev/null >/dev/null
if [ "$?" -eq 1 ] || [ -z "$GRANT_GRP" ] ; then
    echo "Grant group \"$GRANT_GRP\" does not exist!"
    exit 1
fi
 
# Reset ACL entries if configured.
if [ ! -z "$RESET_ACL_ENTRIES" ] && [ x"$RESET_ACL_ENTRIES" = x"yes" ]
then
    setfacl -Rbn "$DIR"
fi
 
# Set default ACLs.
setfacl -dm u::rwx,m::rwx,g::rx,o::rx "$DIR"
setfacl -R -dm u::rwx,m::rwx,g::rx,o::rx "$DIR"
# Grant access to dirctory user and group.
setfacl -R -dm u:"$USR":"$DIR_USR_PRM",g:"$GRP":"$DIR_GRP_PRM",o::"$DIR_OTR_PRM" "$DIR"
setfacl -R -m u:"$USR":"$DIR_USR_PRM",g:"$GRP":"$DIR_GRP_PRM",o::"$DIR_OTR_PRM" "$DIR"
 
case "$ACTION" in
    revoke )
        # Revoke access to system user.
        setfacl -R -dx u:"$GRANT_USR",g:"$GRANT_GRP" "$DIR"
        setfacl -R -x u:"$GRANT_USR",g:"$GRANT_GRP" "$DIR"
        ;;
    * )
        # Grant access to system user.
        setfacl -R -dm u:"$GRANT_USR":rwx,g:"$GRANT_GRP":rwx "$DIR"
        setfacl -R -m u:"$GRANT_USR":rwx,g:"$GRANT_GRP":rwx "$DIR"
        ;;
esac