tags:

views:

716

answers:

1

I have file permissions issues that I would like to resolve without resorting to making everything world writable.

I'm writing files to a NetApp SAN. The directory I'm writing to is owned by the devel user, and has a group of devel with group-writable permissions (0775). The username I'm writing as is in the username and devel groups.

The problem appears to be the SAN only checks the first group, so I get permission denied. If I use the newgrp or sg commands to change my group to devel, then I am able to write to the directory.

The script attempting to do the writing is written in Perl, but it is started remotely from another machine via ssh and some bash scripting.

I cannot change the target directory to be in the username group, because there are other developers and they're in different groups (but we all share the devel group).

I cannot make Perl script itself setgid, because we run different environments (devel, test, qa, production, etc) with appropriate groups, and I don't want to manage file permission bits at that level.

I cannot use the POSIX setgid function from within the Perl script because it doesn't start as root (and I have no way to ever get root), so I get permission denied. Assigning to $) and $( gives the same result.

I cannot use the newgrp command from bash because newgrp doesn't take any arguments, it just starts a new interactive shell (with any following commands executed after the new shell has exited).

I also cannot use newgrp to start a new shell and spawn the Perl script from there, since the Perl script is executed on a remote machine over an ssh connection. The script will get a 'fresh' shell on the remote machine under my default group, not the group set via newgrp on the local machine.

I cannot use the sg command because it only takes a single argument. I quote the full command line, including known arguments. However, the way we start remote processes over ssh includes passing local arguments along in the "$@" bash variable. In other words, I can do a process start or process stop, and the process script handles the ssh command and passes along any local arguments I've typed in using "$@". I've tried writing a wrapper, but have discovered we use a variety of interesting local argument forms, and am hesitant to dive into the necessary quoting and escaping nightmare.

So, my question is: is anyone aware of some other means of setting the effective group id for a running process, from Perl or bash? Is there a multi-argument form of sg?

+3  A: 

At the top of your Perl script, can't you put this:

if ( 0+$( != DEVEL_GROUP_ID ) { # primary group isn't devel
  my(@reinvoke) = ($0, map {quotemeta} @ARGV);
  exec('/usr/bin/sg', 'devel', "@reinvoke");
  die("/usr/bin/sg not found!  Can't change group!");
}

That is, let Perl do the necessary invoking of sg.

Daniel Martin
Your approach worked. I did have to modify it slightly to propagate custom environment variables across the exec: I added a "PERL5LIB=$ENV{PERL5LIB}" (and others) into @reinvoke before $0.
Andrew Barnett
One thing you'll want to be careful about: run the values of the variables through quotemeta first.
Daniel Martin
I've also discovered that X forwarding doesn't like it when you change the effective group. Part of this system is a perl-Tk GUI, and it uses the same framework code to run itself. I had to code an exception that checked for Tk code, and not change the group if found.
Andrew Barnett
As far as quoting the variable - we already had a helper script that set up the command line for the framework. It's used to transfer the local environment to the remote machine over ssh. It was trivial to plug it in for a local exec call, and it already deals with quoting the environment variables.
Andrew Barnett