Techniques for Simulating Multiple Group Ownership
Doug Morris
How often as a system administrator have you wished
you could control
access to data files and directories with some of the
same ease and
flexibility afforded by your favorite DBMS (Database
Management System)?
Specifically, how often have you wished you could provide
different
modes of access (READ/UPDATE) to selected sets of users
without
replicating the data for each set of users? You can
do this on any UNIX
system. Using the techniques described in this article,
you will be able
to accomplish the above without incurring the expense,
overhead, and
hassle of moving your data into a DBMS.
As a system administrator, you would like to give two
different groups
of users (the READ group and the UPDATE group) different
permissions to
the same data directory (DATA).You would like each user
in the READ
group to have read-only access to the files contained
within DATA. Users
in the UPDATE group should have both read and write
access to the files
contained within DATA, and users not in either READ
or UPDATE
(other/world) should have no access to DATA.
At first, the solution may appear straightforward:
1) Define the two groups READ and UPDATE in the group
file;
2) Use chgrp to assign the group ownership of DATA,
and chmod to assign
the permissions.
The catch is that DATA can only have one group owner,
either READ or
UPDATE, not both.
If you try the above method starting with the READ group,
the command
sequence:
chgrp -r READ DATA
chmod g=rx DATA
cd DATA
chmod g=r *
works correctly for the READ group. It assigns the group
owner of READ
to the DATA directory and to the files under DATA by
performing a
recursive chmod (-r option) on the DATA tree. It also
grants read and
search access to the READ group to the directory DATA,
and read access
to all files immediately under DATA.
The problem arises when you continue with the UPDATE
group. You get
stopped by the first command:
chgrp -r UPDATE DATA
This changes the group owner from READ to UPDATE; thus,
the READ
ownership and permissions are lost. You could alternatively
duplicate
the DATA directory and its files, and let the READ group
own the
original and the UPDATE group own the copy. But, keeping
the two
separate copies in sync would be difficult and cumbersome.
If your UNIX flavor supports Access Control Lists (ACLs),
you could
extend the mode permissions with the following permit
rules:
For DATA,
permit rwx g: UPDATE
and for all files under DATA,
permit rw g: UPDATE
ACLs can be handy. They can be used to supplement mode
permissions and
extend/deny access to specific users or groups of users.
Unfortunately,
most UNIX systems to not support ACLs. Even if they
are supported, ACLs
usually do not extend across NFS mounts and may be difficult
to
maintain. For example, each file added under data may
require additional
action to assign the ACL if there is no way to define
inheritance.
Fortunately, there are techniques using control directories
that are
simpler, possibly easier to maintain, and extensible
to any Unix system.
The concept behind these techniques is simple. Use a
control directory
as a barrier to cut off access to the underlying subtree.
If the control
directory is owned by READ with group permissions of
g=rx, o=, then only
the owner and users in the READ group will have access
to the files or
directories in the underlying subtree. All other users
will have no
access, because search permission is missing for other/world
(o=).
Technique 1 - Single Control Directory with Dual Memberships
For this technique, the UPDATE group must be defined
differently. UPDATE
will not be a group unto itself, instead it will be
a permission
attribute defined in terms of two new groups READ and
WRITE.
The new READ group will be the union of the natural
READ group and the
new WRITE group. The new WRITE group will be identical
to the natural
UPDATE group. Using these groups, define a control directory
(CONTROL)
with a group owner of READ and permissions of g=rx,
o=.
cd ../DATA
mkdir CONTROL
chgrp READ CONTROL
chmod g=rx, o= CONTROL
Directly underneath the CONTROL directory is the DATA
directory. For the
DATA directory and its subtree, define the group owner
to be WRITE with
permissions of g=rwx, o=rx for DATA, and g=rw, o=r for
all files within
DATA.
chgrp -r WRITE DATA
chmod g=rwx, o=rx DATA
cd DATA
chmod g=rw, o=r *
The above structure (illustrated in Figure 1) implements
the desired
solution, in that, no user outside the READ or WRITE
groups has any
access to the DATA subtree. Users in the READ group
have group search
access to the CONTROL directory, so they may reference
the DATA subtree.
These users obtain read access to the DATA subtree through
the
permissions assigned to other/world. The group permissions
do not apply
because they are not members of the WRITE group; however,
they are by
definition members of other/world.
Users in the WRITE group have search access to the CONTROL
directory via
the permissions assigned to other/world. They obtain
read and write
access to the DATA subtree via the group permissions
for WRITE.
This technique works best on UNIX systems derived from
BSD. BSD supports
concurrent participation in multiple groups though an
extension called
the supplementary group set. This supplementary group
set is simply an
array of group ids (gids) initialized at login to contain
the gids of
all groups in which the login user is a member. Note
that it may not be
possible to accommodate all groups of which the user
is a member. The
array size is kernel defined (NGROUPS_MAX parameter)
and usually fixed
at 16 to 32 entries - 16 is the most common value because
it is the
maximum number officially supported by NFS.
The supplementary group set is inherited by each process
and defines all
gids for which group permissions are enabled. On systems
not supporting
the supplementary group set, the array size is essentially
one - the
effective gid. The effective gid can be dynamically
changed via the
newgrp command, which takes a group name or gid as its
argument. For
UPDATE users to obtain write access on these systems,
they would have to
do the following:
newgrp READ
cd CONTROL
newgrp WRITE
This change of group is necessary because concurrent
membership is not
active as in BSD systems.
Another useful feature of BSD systems is group inheritance.
If you issue
the command:
chmod g+s DATA
then any file or directory created under DATA will automatically
inherit
the group owner of WRITE instead of the user's primary
or effective
group.
For systems not supporting supplementary groups, or
in cases where dual
membership in the READ and WRITE groups is not desirable,
the following
technique may be more useful.
Technique 2 - Dual control directories with single memberships
For this technique, define the READ and UPDATE groups
according to their
natural definition, and define two separate control
directories
CONTROL_R and CONTROL_U with a common parent of PROTECT.
Let the READ
group be the group owner of CONTROL_R, and the UPDATE
group by the group
owner of CONTROL_U. Assign permissions of g=rx, o= to
CONTROL_R, and
g=rwx, o= to CONTROL_U.
cd PROTECT
mkdir CONTROL_R CONTROL_U
chgrp READ CONTROL_R
chgrp UPDATE CONTROL_U
chmod g=rx, o= CONTROL_R
chmod g=rwx, o= CONTROL_U
Now the tricky part: move the directory DATA under CONTROL_R
and let
DATA be owned by UPDATE with permissions of g=rwx, o=rx.
Similarly, let
all files under DATA be owned by UPDATE with permissions
of g=rw, o=r.
Create a hard link to DATA under the CONTROL_U directory
(on many
systems you will need to be root to do this).
cd CONTROL_R
mv <full pathname of DATA> DATA
chgrp -r UPDATE DATA
chmod g=rwx, o=rx DATA
cd DATA
chmod g=rw, o=r *
cd <full pathname of PROTECT>/CONTROL_U
ln -f ../CONTROL_R/DATA DATA
CONTROL_R and CONTROL_U are now parents of the same
directory, DATA. The
permissions of the control directories and DATA (illustrated
in Figure 2)
are such that users in the UPDATE group can obtain
read or write
access through the path PROTECT/CONTROL_U/DATA, and
users in the READ
group can gain read access through the path PROTECT/CONTROL_R/DATA.
All
other users have no access, and neither group can gain
access though
the other's path. Note that the hard link to the directory
was created
by using the -f option of the ln command. This option
is supported by
SunOS and other UNIX systems, but may not be supported
or interpreted in
the same way on all UNIX systems (i.e., the GNU version
of ln uses the
-d or -F options to force a hard link to a directory).
Unfortunately,
not all UNIX systems support hard links to directories,
SGI Irix and
Linux are two common examples. For these systems, the
same technique can
be used, but the files in the directory will have to
be linked
individually.
Summary
I have described techniques that will allow you to control
access to
data files and directories with some of the same ease
and flexibility
afforded by your favorite DBMS - without the hassle,
and expense of
moving the data to a DBMS.
Both of the described techniques were used to simulate
a form of
multiple group ownership. These techniques are useful
because they allow
you to define separate groups with different access
rights to the same
data (typically one group will be read-only, and the
other will be
read-write).
Technique 1 exploits the concurrent group membership
allowed on BSD
systems. It is straightforward and easy to implement
using intersecting
READ and WRITE groups (UPDATE access is granted though
dual membership
in both the READ and WRITE groups).
Technique 2 is suited to conventional UNIX systems or
to cases in which
intersecting groups are not desirable. This technique
is more
complicated to implement and requires the construction
of a hard link to
a directory (hard links are usually not allowed to span
physical
partitions, and directory hard links may not be supported
on all
systems). It also requires the construction of two control
directories
with differing group ownerships and access permissions.
Users in either
the READ or UPDATE group must specify the correct path
though the proper
control directory or access will be denied.
About the Author
Doug Morris has a B.S. in Mathematics and an M.B.A.
in Management
Information Systems. He is a UNIX enthusiast and long-time
Open Systems
advocate. He has been an active participant in XOpen,
including holding
an elected office on the XOpen User Council Executive.
He has held
various positions in technology evaluation and management
at several
Fortune 500 companies, including his current position
as a Systems
Specialist/Software Engineer at a major international
oil company. He
can be reached at his personal email address of damorri.msn.com.
|