Oracle Linux : Using ACL's to read files you can't see

Part of our business is automated licence auditing of Oracle products which means we ask our clients to install a small agent on their servers which will report to a central server various bits of information needed to calculate the number and type of licences that need to be acquired from Oracle. While we advise that this agent be run as root as it is the most reliable way to ensure everything is properly collected, many of our clients, especially the larger ones, and not just the banks, are very cagey about running an agent as root on their servers. One of the issues we had to address when running our agent with an unprivileged, non-root, account was how do we read the various files that contain licensing information? For databases, we read everything we need from the database itself, but for other products such as Weblogic we need to locate the config.xml files for each domain and parse them.
This become rather difficult to do when you are given a system account that does not belong to the oinstall or dba group, and thus cannot access files belonging to Oracle. The initial thought was to locate the files and run a few chmod +r commands. That was quickly dropped as the impact on the Oracle binaries was unknown, and these modifications would be most likely over-written the next time the dba executed the root.sh script, so enter the ACL or Access Control List.
ACLs are a seperate tool or method to manage access to specific files or directories, be it in read, write or execute mode than is completely independent from the classical *nix file rights. ACLs are available, though not always configured, on all Unix/Linux flavours. There are plenty of examples on the web of how to grant a read, write or execute right to a specific file, but I spent a lot of time trying, and failing, to find anything about recursive rights in order to drill down a path to a file.
How do you let system user ‘easyetr’ read file /u01/app/oracle/products/middleware/gc_inst/Part of our business is automated licence auditing of Oracle products which means we ask our clients to install a small agent on their servers which will report to a central server various bits of information needed to calculate the number and type of licences that need to be acquired from Oracle. While we advise that this agent be run as root as it is the most reliable way to ensure everything is properly collected, many of our clients, especially the larger ones, and not just the banks, are very cagey about running an agent as root on their servers. One of the issues we had to address when running our agent with an unprivileged, non-root, account was how do we read the various files that contain licensing information? For databases, we read everything we need from the database itself, but for other products such as Weblogic we need to locate the config.xml files for each domain and parse them.
This become rather difficult to do when you are given a system account that does not belong to the oinstall or dba group, and thus cannot access files belonging to Oracle. The initial thought was to locate the files and run a few chmod +r commands. That was quickly dropped as the impact on the Oracle binaries was unknown, and these modifications would be most likely over-written the next time the dba executed the root.sh script, so enter the ACL or Access Control List. ACLs are a separate tool or method to manage access to specific files or directories, be it in read, write or execute mode than is completely independent from the classical *nix file rights. ACLs are available, though not always configured, on all Unix/Linux flavours. There are plenty of examples on the web of how to grant a read, write or execute right to a specific file, but I spent a lot of time trying, and failing, to find anything about recursive rights in order to drill down a path to a file.
How do you let system user ‘easyetr’ read file /u01/app/oracle/products/middleware/gc_inst/user_projects/domains/GCDomain/config/config.xml ?
Well you need to grant an ACL execute right on each folder starting from the root, and that’s not mentioned anywhere:

setfacl -m u:etruser:x /u01/
setfacl -m u:etruser:x /u01/app/
...
setfacl -m u:etruser:x /u01/app/oracle/product/middleware/gc_inst/user_projects/domains/GCDomain/config/

And finally, grant the ACL to the file itself, that’s the fully documented bit:

setfacl -m u:etruser:r /u01/app/oracle/products/middleware/gc_inst/user_projects/domains/GCDomain/config/config.xml

So as a pre-requirement, our clients needs to run a find, as root, to locate all config.xml files that may be in /u01 or below, the egrep -v will exclude all the stuff we don’t actually need:

ORAFILES=`find /u01 -name config.xml | egrep -v "(samples/|/ext/|/backup/|/diag/|/oc4j/)"`

We start parsing every line coming out of the find command, first get the path up to and excluding the file

for f in $ORAFILES
do
basedir=`dirname $f`

Then, we get the name of the file itself, last part of the find

   basenam=`basename $f`

Chop up the path into elements by replacing the slashes by spaces, awk does not work on some OS, so use tr

   direlt=`echo $basedir| tr '/' ' '`
   for dir in ${direlt[*]}
   do

Build the path one element at a time

      acldir=${acldir}/${dir}

In two parts just to add the slash at the end:

      acldir2=${acldir}/

Add the setfacl command to allow user etruser to browse through the directory without being able to read it

      echo "setfacl -m u:etruser:x ${acldir2}" >> commands.sh
   done

Do the same thing for the file this time with an ‘r’ instead of an ‘x’

   echo "setfacl -m u:etruser:r ${acldir2}${basenam}" >> commands.sh
   acldir=""
done

That will write all the commands you need to run in the command.sh script which you can check and edit prior to running with a

 sh command.sh

No need to make the file executable here, the sh will do the trick
While the ACLs will allow you to read the file with your favourite editor (cat, vi , more, etc.), a test on file existence and readability such as

[ -f /u01/app/oracle/products/middleware/gc_inst/user_projects/domains/GCDomain/config/config.xml ]

will fail, for some reason, if you need to test existence, then best do a grep foo config.xml and test the return code:
0: foo is in the file, 1: it is not, 2: can’t read the file at all, and there you go!
That will of course work on Linux, but on Solaris and AIX, the syntax will be radically different, having seen one of our clients struggle with it, though the concept of granting at each level down to the file itself is the same.