For those unfamiliar with op, one can think of op as being similar
to sudo. As taken from the man page (op.1):
The op tool provides a flexible means for system administrators to grant trusted users access to certain root operations without having to give them full superuser privileges. Different sets of users may access different operations, and the security-related aspects of environment of each operation can be carefully controlled.(As an aside, op can be compiled and run on Solaris, FreeBSD, and Linux,
as well as other UNIX types.) In order for a non-root user to make use
of op, an appropriate configuration entry may be set up within op.conf.
For local builds of op, this file will likely reside at:
/usr/local/etc/op.confOf note, op's build configuration also provides the availability of
an includes directory, such as:
/usr/local/etc/op.d/*.confAll files within /usr/local/etc/op.d with an extension of '.conf' would
be read as part of the op config, subsequently to /usr/local/etc/op.conf,
and in lexical order. All config files must be owned by u:g root:root
(or root:wheel) with only user permissions set, thus 600.
Assuming an appropriate configuration entry for a user, the user, once
logged in to the host, can access the resources provided by op as follows
(shell prompt: server [0]):
server [0] /usr/local/bin/op someMnemonic [arg...]**** Configuration ****
While the manpage for op is considered to be the definitive source of
documentation (and should be referenced as necessary), the following is
simply a brief overview of how to configure op.
In example 1, user 'jdoe' is setup to allow the use of Solaris command
'snoop'. For illustrative purposes only, preceding each config file
line is the line number.
++++ Example 1 ++++
/usr/local/etc/op.conf entry:
1 # A simple example config for op(1). See the man page 2 # for more information or op.conf.complex for a complex 3 # multi-user/multi-system configuration. examples under 4 # /usr/local/share/doc/op-1.32 5 # 6 # 7 # 8 # 9 #executed from command as 'op snoop -d port bge0 80' 10 watchTraf /usr/sbin/snoop $1 $3 $2 $4 ; 11 users=jdoe 12 uid=root 13 gid=root 14 passwordIn the above configuration entry, we have the following:
* lines 1-9 are all comments, beginning with a pound sign (#). * line 10 defines the op function with a mnemonic (watchTraf), sets the command to execute (/usr/sbin/snoop), and defines expected arguments. Of note, the arguments on line 10 are ordered $1, $3, $2, $4, thus when op processes the command line, it will switch args 2 and 3 during command execution. (The arguments were deliberately positioned in the config file this way for point of illustration, though may be in any logical and sane order.) Line 10 ends with a semicolon (;) to denote the beginning of any options acted upon by op. * line 11, first option, defins option 'users' with a value of 'jdoe'. Any user listed here is allowed to executed this op function. * line 12 sets option 'uid' with a value of 'root'. This is the euid that the command called in this op function will be executed as. * line 13 sets option 'gid' to a value of 'root'. This is the egid that the command called in this op function will be executed as. * line 14 sets option 'password'. This option tells op to prompt and require the user's login password prior to execution of the command called within this op function.Based on the above, user 'jdoe' has logged into 'server' and wants op
to perform function 'watchTraf', which is to run 'snoop' with parameters
$1 $3 $2 $4. This will be run as root:root and will require user jdoe's
login password in order to be executed. User 'jdoe' would execute and
see the following (shell prompt: jdoe@server [0]):
jdoe@server [0] /usr/local/bin/op watchTraf -d port bge0 80 Password:Upon successfully entering the login password for jdoe, /usr/sbin/snoop,
based upon the config entry above, would be executed as:
/usr/sbin/snoop -d bge0 port 80Upon unsuccessfully entering the login password for jdoe, the following
error would appear:
watchTraf: permission denied by opOf note, a user can see what op functions have been defined for them by
executing op with parameter '-l'. The following would be what jdoe
would see:
jdoe@server [0] /usr/local/bin/op -l watchTraf /usr/sbin/snoop $1 $3 $2 $4If the user has nothing configured, no output is generated.
With regards to example 1, supposing that more than one user needed
to execute this same command, we could define a user list, as seen in
example 2:
++++ Example 2 ++++
1 # A simple example config for op(1). See the man page 2 # for more information or op.conf.complex for a complex 3 # multi-user/multi-system configuration. examples under 4 # /usr/local/share/doc/op-1.32 5 # 6 # user lists 7 SNOOP_USERS=(jdoe|fsinatra) 8 # 9 #executed from command as 'op snoop -d port bge0 80' 10 watchTraf /usr/sbin/snoop $1 $3 $2 $4 ; 11 users=SNOOP_USERS 12 uid=root 13 gid=root 14 password 15 help="watchTraf -d port bge0 80"For the most part, example 1 and 2 have remained the same with the
exception of 4 lines. For brevity, only those 4 will be discussed:
* line 6 is still a comment * line 7 now defines a variable of 'SNOOP_USERS' with a value of '(jdoe|fsinatra)', thus a value of 'jdoe' or 'fsinatra'. * line 11 now sets 'users' to a list made up of variable 'SNOOP_USERS', which substitutes in values of 'jdoe' or 'fsinatra' * line 15 sets option 'help' to be value 'watchTraf -d port bge0 80'. This option affects the output to executing 'op -l', substituting the output of the mnemonic with the value of 'help'.With the new updates to the config, either 'jdoe' or 'fsinatra' could
log into the host and execute op function 'watchTraf', assuming they
have supplied their respective login passwords when prompted.
For a third example, essentially re-using example 1, a shell will be
spawned for user 'jdoe', allowing access as if 'jdoe' su'd to user
'fsinatra'. For the example, assume 'jdoe' is a member of group
anons(501) and fsinatra is a member of group rpack(647).
++++ Example 3 ++++
1 # A simple example config for op(1). See the man page 2 # for more information or op.conf.complex for a complex 3 # multi-user/multi-system configuration. examples under 4 # /usr/local/share/doc/op-1.32 5 # 6 # 7 # 8 # 9 # spawn a shell as euid:egid fsinatra:rpack 10 shell MAGIC_SHELL ; 11 users=jdoe 12 uid=fsinatra 13 gid=647 14 passwordIn the above, lines 1-9 are all comments.
* line 10, define function mnemonic 'shell', set the command to 'MAGIC_SHELL', denote beginning of op options (;). 'MAGIC_SHELL' is a predefined, internal variable to op which uses the $SHELL environment variable of the euid being executed as. Thus if fsinatra's $SHELL is set to /bin/ksh, upon successful execution of the op function 'shell', jdoe will have a shell of /bin/ksh running as fsinatra:rpack. * line 12, option 'uid' is value 'fsinatra'. * line 13, option 'gid' is value '647'. Of note, both 'uid' and 'gid' can be either a numeric user / group id or a login / group name.Example 3 effectively allows user 'jdoe' to execute commands with any
privileges available to user 'fsinatra', group 'rpack', from within korn
shell, as /bin/ksh has been specified by fsinatra's $SHELL environment
variable. A test run of the function set in example 3 could be seen below:
jdoe@server [0] /usr/bin/id -a uid=783(jdoe) gid=501(anons) groups=501(anons) jdoe@server [0] /usr/bin/who am i jdoe pts/15 Jan 1 20:30 jdoe@server [0] /usr/ucb/whoami jdoe jdoe@server [0] /usr/local/bin/op shell Password: fsinatra@server [0] /usr/bin/id -a uid=432(fsinatra) gid=647(rpack) groups=647(rpack) fsinatra@server [0] /usr/bin/who am i jdoe pts/15 Jan 1 20:30 fsinatra@server [0] /usr/ucb/whoami fsinatra fsinatra@server [0] exit jdoe@server [0]The above illustrates that the effect of 'MAGIC_SHELL' is quite similar to
if user 'jdoe' has used '/usr/bin/su -' to switch user to user 'fsinatra'.
The euid and egid are both updated to fsinatra:rpack, fsinatra's shell
is spawned off, commands executed within are executed as user fsinatra /
group rpack... the only noticeable difference is that rather than entering
the login password for 'fsinatra', user 'jdoe' can simply user their own.
Regarding the config file, indentation seen within all provided examples
is required. op perceives any line beginning with an alphanumeric
character as the beginning of either a function or a variable. (Line
numbers have only been included for the point of discussion and will
not otherwise exist.) Also of note, all op variables are alphanumeric
(underscores are allowed), and must be UPPER_CASE. To allow the user to
retain their own environment settings during op runtime, 'environment'
can be passed as an optional config parameter. Additionally, environment
variables can be passed by identifying them as $VAR=VARIABLE. As a final
config modification, we can set limits on a user's access, specifying
where they can log in from and an expiration of their access:
1 MYPROG_USERS=(jdoe|fsinatra) 2 myProg /usr/local/bin/prodApp -h $2 -u $1 -p ; 3 users=MYPROG_USERS,jsmith@devbox.example.com/201102151730 4 uid=proguser 5 gid=proggroup 6 environment 7 password 8 help="myProg USERNAME HOST" 9 $MYPROG_LOG_DIR=/bitbucket/logsOn line 3 in the above example, access is given to users within the
'MYPROG_USERS' list defined on line 1. Also, 'jsmith' is given
access only from 'devbox.example.com' and that access expires on 15
Feb 2011 at 5:30 pm localtime. (The format for user access expiration
is YYYYMMDD[HH[MM]].) On line 6, we allow users to retain their own
environments during op runtime, however, on line 9 we deliberately set /
override the MYPROG_LOG_DIR environment variable.
**** Further information ****
As this post is only meant to give a brief overview of common
configuration / usage of op, it is not all encompassing.
For further information, please see the manpage (op.1),
/usr/local/etc/op.conf, /usr/local/share/doc/op-1.32/op.conf.complex,
and http://swapoff.org/wiki/op. op will likely not be installed on
your system by default, though can be downloaded for compiling from
http://swapoff.org/wiki/op#Download. op was originally written by Tom
Christiansen and Dave Koblas and is currently maintained by Alec Thomas.
At the time of this writing, op is at version 1.32.