An XML interface for UNIX and Linux filesystems extended ACLs
Novell Cool Solutions: Feature
By Michel Bluteau
Digg This -
Posted: 5 Nov 2004
Michel Bluteau, Novell
A discussion on how XML can be implemented as an interface to POSIX filesystem Extended Access Control Lists.
This document is the result of some research and experimentation with UNIX and Linux filesystems traditional ACLs and extended ACLs based on POSIX 1003.1e/1003.2c. For more information, take a look at "POSIX Access Control Lists on Linux".
The main goal I have in mind is to find a way to migrate filesystems from Windows, UNIX and NetWare to Linux, while providing granular ACLs and taking advantage of a Graphical User Interface, or GUI, in order to manage filesystem ACLs. While the example described in this document should not be positioned as a full blown solution for managing filesystems on a Linux or UNIX server, it may be useful to illustrate the value behind having an interface like XML in front of a UNIX or Linux filesystem, because many applications or development platforms can directly interface with XML. For example, eDirectory through Nsure Identity Manager (aka DirXML) can interface and synchronize information through an XML interface, and commercial reporting applications like Crystal Report can consume data in XML format. Also, development platforms like Miscrosoft .net or Mono can interface with XML.
The solution described in this example should work on pretty much any version of Linux and UNIX. In order to take advantage of extended ACLs, they must be supported by the operating system or kernel(e.g. most UNIX, SUSE Linux 9). In order to take advantage of the extended ACLs one's filesystem must implement the POSIX extended ACLs, something that can be verified quickly with the help of the two commands setfacl and getfacl. If one gets the error Operation not supported, then the filesystem needs to be upgraded or files need to be moved to another file system.
Traditional filesystem ACLs versus POSIX 1003.1e/1003.2c ACLs
The traditional and familiar filesystem ACLs on UNIX and Linux are somewhat limited when compared with ACLs found on Windows NTFS and NetWare NSS. The 3 privileges which are available are read(r), write(w) and execute(x), and they can be granted to the user(u) that owns the file, the group(g) that owns the file, or to all other(o) users, which includes all possible users and groups who don't own the file.
Let's say for example that we need a shared filesystem for a project where some users may be able to create documents or modify the documents that they have created, while other users may be allowed to read but not modify or create documents. Since there are other users on the same server(s) for which access should be denied to the project's shared filesystem, other(o) cannot be used to grant read-only access, so we may need to group users in 2 groups, let's say projectAdmins and projectReaders. For a given document, we could set the group ownership to projectAdmins(g), and remove privileges for other(o), but still we fall short of meeting our goal mainly because there is only one group(g) or one user(u) that can own the document at any given time.
If we start to take advantages of enhanced ACLs with the commands setfacl and getfacl, then we can successfully meet our goal. Let's say that we want to setup ACLs for a file called document1. We could proceed as below:
chgrp projectAdmins document1 (sets group ownership to projectAdmins)
chmod g=rw document1 (sets permissions for the projectAdmins group to read/write)
chmod o-rwx document1 (removes privileges for other)
setfacl -m g:projectReaders:r document1 (sets read privileges for projectReaders)
For this example, the output of the getfacl command should look like this:
linux:/home/root/testacl # getfacl document1 # file: document1 # owner: root # group: projectAdmins user::rw- group::rw- group:projectReaders:r-- mask::rw- other::---
We can see that members of the projectReaders group are granted the read permission while the members of the projectAdmins group, who own the file, are granted the read and write permissions.
This example is only one among many which could have been used to illustrate the fact that extended ACLs may be useful under some circumstances. In practice, one could leverage directory ACLs instead of file ACLs in order to manage shared filesystems in a more efficient way.
The choice of an interface for managing ACLs and extended ACLs
With the commands setfacl and getfacl, one finds the same kind of granularity for filesystem ACLs that one gets with the Windows NTFS or NetWare NSS filesystems. However, getfacl and setfacl are text based utilities and the lack of a GUI interface like the ones for Windows and NetWare filesystems can be a showstopper for someone who wants to migrate user data to a Linux server. There is a java-based GUI available today for Solaris, jfacl, but that is about it. For the other UNIX platforms and for the Linux platforms that support extended ACLs, good old text-based commands with switches and arguments are the rule.
However, this situation is likely to change in the very short term, since many simultaneous groups are working on this problem. For example, Novell is currently working on porting NSS to Linux. And since the source code is available for the libacl-devel package that implements the extended ACLs on Linux, one could in theory write a graphical interface or implement a way to expose the information in a format that can be leveraged by applications talking LDAP or XML or Delimited Text, etc.
I made the decision to explore how an XML interface for the extended ACLs could be implemented. After discussing with a few individuals, some recommended to me that I use C, others recommended to me that I use Python or Perl. I finally decided to use Bash scripts, even if this is probably not the most efficient way to get to my goal, because I wanted a quick way to test the concept and figure out if that could be a valuable approach, regardless of how the interface is being implemented.
Implementing an XML interface for EACLs using Bash scripts
In my example, my goal is to generate one XML output file for each directory, subdirectory, or file, that is under a specific directory. In order to accomplish that goal, I have to go through a few steps:
- Identify the directory/subdirectory tree, i.e. identify each and every subdirectory item and the relationships among them.
- Generate an XML document for each directory/subdirectory that is part of the tree.
- Identify each and every file that is contained in the tree, and its location.
- Generate an XML document for each of these files.
In order to achieve the above 4 steps, I am leveraging a few Bash scripts that can be added to the path or copied into a directory like /usr/local/bin. Also, one must create a directory structure to receive the XML documents, for example, /root/acl2xml/output.
The first script I am calling is acl2xmlEXEC:
find -type d | sed -e 's/^./execXML \/home\/root\/testacl/' > /root/acl2xml/execXMLmulti chmod u+x /root/acl2xml/execXMLmulti /root/acl2xml/execXMLmulti
acl2xmlEXEC's first action is to find all items of type directory(find -type d) for the tree under /home/root/testacl. One could add the -mtime switch in order to capture only the directories that have been modified after a certain date/time. The result is then written to a file, execXMLmulti, in the form of one command per line, one for each subdirectory. The command is a script, execXML, which I will describe shortly. The execXMLmulti is also a script so we then change its mode to executable(chmod u+x) and execute it on the last line.
The resulting script execXMLmulti will look something like this:
execXML /home/root/testacl execXML /home/root/testacl/captures
The script that takes care of each directory, execXML, goes like this:
cd $1 ls -A -1 -p | grep '/' | sed -e 's/^/getdacl2XML /' -e 's/\///' > /root/acl2xml/execXML2 file * | sed /directory/d | cut -d: -f 1 | sed -e 's/^/getfacl2XML /' >> /root/acl2xml/execXML2 chmod u+x /root/acl2xml/execXML2 /root/acl2xml/execXML2
execXML takes one argument, the subdirectory, which is represented by $1. After that, it positions itself in the directory $1, then it creates a 3rd script, execXML2, which will call yet another script, getdacl2XML, for each subdirectory, and a separate script for files, getfacl2XML. These two scripts are the actual scripts that generate XML documents, one per sub-directory or file contained it the $1 sub-directory. Here, grep, cut and sed are used to create the execXML2 intermediate script with the right format:
getdacl2XML captures getfacl2XML license.txt getfacl2XML test
Here is the getfacl2XML script:
getfacl $1 > /root/acl2xml/temp/"$1"tmp echo \<posixFile\> > /root/acl2xml/output/"$1".xml echo \<path\>`pwd`\<\/path\> >> /root/acl2xml/output/"$1".xml sed -e 's/# file: /\<file\>/' -e 's/# owner: /\<owner\>/' -e 's/# group: /\<group\>/' -e 's/user::/\<userPriv\>/' -e 's/user:/\<userPriv\>/' -e 's/group::/\<groupPriv\>/' -e 's/group:/\<groupPriv\>/' -e 's/mask::/\<mask\>/' -e 's/other::/\<otherPriv\>/' -e '/^<file/s/$/\<\/file\>/' -e '/^<owner/s/$/\<\/owner\> /' -e '/^<group\>/s/$/\<\/group\>/' -e '/^<userPriv/s/$/\<\/userPriv\>/' -e '/^<groupPriv/s/$/\<\/groupPriv\>/' -e '/^<mask/s/$/\<\/mask\>/' -e '/^<otherPriv/s/$/\<\/otherPriv\>/' /root/acl2xml/temp/"$1"tmp >> /root/acl2xml/output/"$1".xml echo \<\/posixFile\> >> /root/acl2xml/output/"$1".xml rm /root/acl2xml/temp/"$1"tmp
This script looks complex, but all it accomplishes is to take the output for the command getfacl and translate it into XML. An example is shown below:
linux:/home/root/testacl # cat /root/acl2xml/output/license.txt.xml <posixFile> <path>/home/root/testacl</path> <file>license.txt</file> <owner>root</owner> <group>root</group> <userPriv>rw-</userPriv> <userPriv>user2:r--</userPriv> <groupPriv>r--</groupPriv> <groupPriv>group1:r--</groupPriv> <otherPriv>r--</otherPriv> </posixFile>
The getdacl2XML script is similar to getfacl2XML, but the object type is posixDirectory instead of posixFile:
linux:/home/root/testacl # cat /root/acl2xml/output/captures.xml <posixDirectory> <path>/home/root/testacl</path> <file>captures</file> <owner>root</owner> <group>root</group> <userPriv>rwx</userPriv> <userPriv>user1:r--</userPriv> <groupPriv>r-x</groupPriv> <groupPriv>group1:r--</groupPriv> <otherPriv>r-x</otherPriv> </posixDirectory>
Among all the scripts mentioned above, some are permanent scripts that must be included in the path:
And others are temporary scripts generated by the above scripts for processing the information:
-/root/acl2xml/execXML2 (one instance per sub-directory)
Once one gets one XML document for every file and subdirectory under a directory tree, what's left is to use an application that can consume information in XML format, e.g. Nsure Identity Manager(aka DirXML) and import the information. Such an example is briefly described below.
eDirectory classes and attributes for Linux and UNIX filesystem ACLs
The first step required in order to manage ACLs from eDirectory is to define how they are going to be represented in terms of classes and attributes. The following example has been chosen arbitrarily and it may not be the most efficient way to handle filesystem ACLs.
Let's start with the following requirements in mind:
- We will represent files and directories using two separate classes, posixFile and posixDirectory.
- The classes posixFile and posixDirectory can both be contained by posixDirectory.
- For both posixFile and posixDirectory, we need attributes to represent EACLs and identify the path to the file of directory respective to the / filesystem:
-posixDirPath (the sub-directory that contains the file or sub-directory)
-posixFile (the name of the file or directory object)
-posixOwner (the name of the owner)
-posixGroup (the name of the owning group)
-PosixUserPriv (the privileges granted to owner or another user if a username is specified, multi-valued)
-PosixGroupPriv (the privileges granted to the owning group or another group if specified, multi-valued)
-PosixOtherPriv (the privileges associated with Other)
-posixMask (the mask associated with the file or directory)
N.B. For example, if a privilege is in the form rw- for userPriv, that means that the owner has read and write privilege. If another privilege is in the form username:r--, then the privilege is applied to username instead of the owner. The business logic must be able to detect that a privilege is applied to a user other than the owner because of the presence of username: before the privilege. The same applies to group privileges.
Other attributes for eDirectory may be required if one wants to link privileges with user and group objects in eDirectory, if for example LDAP/PAM redirection is used for the managed server(where the filesystem resides) through eDirectory. See:
- Configure Linux to Authenticate to eDirectory via LDAP http://www.novell.com/coolsolutions/feature/1630.html
- PAM/LDAP/start_tls Authentication via eDirectory for Linux Mandrake and EduLinux http://www.novell.com/coolsolutions/feature/1645.html
I have done some experimentations with such a driver, based on the Delimited Text driver that can take XML format for input through the Publisher channel (from the filesystem to eDirectory).
For the Subscriber Channel(from eDirectory to the filesystem) I have used the Delimited Text driver too, but I preferred to use another driver that can just feed the managed server with commands through the remote loader, leveraging a Java class available through Novell Consulting. For example, if I need to setup ACLs on the Subscriber channel, the driver basically executes the setfacl commands with the required arguments and options put together by the business logic contained in the driver.
Since both these drivers are somewhat experimental and more useful to illustrate the concept behind an XML interface in front of a filesystem then to be used in a production environment, I decided to not make them available for now. However, if one has access to a working installation of Nsure Identity Manager and would like to experiment with them, I am willing to share the driver exports and configuration information.
I can be contacted through my email address at mbluteauTAKETHISOUT@novell.com.You can also send me feedback and comments, which are always appreciated.
Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com