Solaris SMF: Delegate Service Control

Solaris SMF: Delegate Service Control

In many of the environments that I deliver to a client we have a concept of an “environment account” this account is the credential set that the environment runs as.  Over time and the maturation of the Service Management Facility (SMF) we have been able to simplify this offering and increase its capabilities.  Today we are going to talk about allowing the environment user to manage a service controlled by SMF.

So lets start by defining the problem.  The basics of the problem is that SMF is what we use to control services in Solaris.  It is incredibly robust and allows for very fine grained dependency managements as well as managing service failure.  One of the primary differences between SMF and init.d is that init.d will only start or stop a service during a runlevel change or a request by a user.  SMF will notice the failure of the service and request an immediate restart, resolving simple service failures.  So we have a lot of good reasons to use SMF, but where is the problem.  We the problem here is simple.  Once we add a service into SMF then only root (or a user who can act on behalf of root) can issue commands to change state of that service.

In order to overcome this we can use Role-based Access Control (RBAC) to delegate control over just that one service.  Obviously you could do sudo, and have a granular policy allowing only certain commands to be executed, but honestly this approach is far more elegant, and frankly it doesn’t require the additional command of sudo to be used at time of invocation.

I am assuming that you already have an SMF created for your service, if you do not you can refer to my article on creating one for your service.  In this example we are going to be using our ebsdev user to control an xvfb service.

CREATE RBAC AUTHORIZATIONS

We are using RBAC to create authorizations, these can go anywhere within the file, Solaris 11 will have a blank file other than some comments, Solaris 10 will have a huge file which includes a bunch of system settings already in there.  I prefer to include them at the end to make a clear delineation between the system and the custom rules.  But this doesn’t matter from a functionality perspective.

# grep xvfb /etc/security/auth_attr
solaris.smf.manage.xvfb:::Manage Xvfb Service States::
solaris.smf.value.xvfb:::Change Xvfb Service Properties::

MODIFY SERVICE TO ALLOW SERVICE STATE AUTHORIZATION

This authorization allows a user to change the state of the service.  Changing the state is not enabling or disabling, we will be adding that separately.  This only allows for service restart.

# svccfg -s application/xvfb setprop general/action_authorization = astring: solaris.smf.manage.xvfb

MODIFY SERVICE TO ALLOW SERVICE VALUE AUTHORIZATION

This authorization allows a user to change values associated with the service.  This is where we are able to allow the disabling and enabling of the service.

# svccfg -s application/xvfb setprop general/value_authorization = astring: solaris.smf.value.xvfb

GRANT USER AUTHORIZATION

Here we need to associate our user with the authorizations we have created.  Important to note here that this will overwrite all existing authorizations, so if you have any already existing then you will need to include them comma delimited in this command.

# usermod -A solaris.smf.manage.xvfb,solaris.smf.value.xvfb ebsdev

TEST SERVICE CONTROL

Here we are just going to give it a quick test and make sure that our user can interact with the services in the way we expect based on our security policies.  Below will test solaris.smf.manage.xvfb

# su - ebsdev
$ svcadm restart xvfb
$ svcs xvfb
STATE          STIME    FMRI
online         May_08   svc:/application/xvfb:default

Now to test solaris.smf.value.xvfb

# su - ebsdev
$ svcadm disable xvfb
$ svcs xvfb
STATE          STIME    FMRI
disabled         12:16:10   svc:/application/xvfb:default
$ svcadm enable xvfb
$ svcs xvfb
STATE          STIME    FMRI
online       12:17:07 svc:/application/xvfb:default

INCLUDE AUTHORIZATION IN A SERVICE DEFINITION

If you already have a service definition, but haven’t yet imported the service you can also include the authorizations into the service definitions to reduce the number of steps which need to be manually executed.  This step is not required for the manual configuration we did above, this is a more sreamlined approach for new services.

# sed -n -e '/property_group/,/\/property_group/ p' xvfb.xml
<property_group name='general' type='framework'>
<propval name='action_authorization' type='astring' value='solaris.smf.manage.xvfb'/>
<propval name='value_authorization' type='astring' value='solaris.smf.value.xvfb'/>
</property_group>

Now when you import it you will be able to avoid the “Modify Service to Allow Service State Authorization” and “Modify Service to Allow Service Statue Authorization” sections.

After you import you can validate that everything got put into the correct place by executing the following.

# svccfg -s application/xvfb listprop general/value_authorization
general/value_authorization  astring  solaris.smf.value.xvfb
# svccfg -s application/xvfb listprop general/action_authorization
general/action_authorization  astring  solaris.smf.manage.xvfb