Modelo de Seguridad de Solaris: RBAC, Roles y Privilegios

Fuente: http://sparcki.blogspot.ch/2010/09/modelo-de-seguridad-de-solaris-rbac.html

Modelo de Seguridad de Solaris: RBAC, Roles y Privilegios

Introducción
En esta ocasión vamos a hacer un repaso -en varias partes- al modelo de seguridad que nos proporciona Solaris y cómo podemos utilizarlos para hacer más seguro nuestro entorno. Ha pasado mucho tiempo desde que empecé el blog, y ahora sí, ya estamos en disposición de poder hablar de esta característica tan potente.

En UNIX el modelo de seguridad se establece como Lectura(r), Escritura(w) y Ejecución(x) para el Propietario, Grupo y Los demás. Un modelo que en un principio era más que suficiente para llevar a cabo las tareas comunes y tener un sistema de seguridad adecuado a las necesidades de aquel tiempo, sin embargo, a día de hoy las cosas son un poco más complicadas.

El modelo UNIX de seguridad, además define que para poder acceder a un puerto inferior a 1024 es necesario tener privilegios de root. Esta medida -en su momento interesante- hace que a día de hoy -con el avance de los exploits, buffer overflow, etc. - pone en riesgo nuestro sistema, veamos un ejemplo.


Un pequeño ejemplo
Nuestro servidor Apache HTTP necesita levantarse en el puerto 80 -y como hemos comentado es necesario tener permisos de root para ello-, por lo tanto, para evitar que todos nuestros procesos de HTTP corran con los permisos de root, nuestro Apache hace un setuid a un usuario no privilegiado para los nuevos procesos de esta forma,  minimiza el posible problema de permisos.  Por ejemplo, si miramos los procesos de nuestro Apache HTTP
www  4076 13484   0 05:17:43 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
root 13484   774   0   mar 25 ?          11:20 /opt/www/apache-1.3.41/bin/httpd
Sin embargo,  sigue quedando un proceso con todos los permisos y es aquí donde podemos tener problemas.


Super User Model
El modelo SuperUser, hace referencia a contar con un usuario "super priviligiado" <root> que no tiene ningún tipo de limitación y de un conjunto de usuarios no privilegiados. Esto supone que no disponemos de un sistema de ajuste fino de asignación, por ejemplo, si queremos que un usuario pueda reiniciar el servicio Apache HTTP, debemos otorgarle permisos de root -o proporcionale la contraseña-, sin embargo, al hacerlo, también le estamos otorgando todos los permisos.


RBAC y Privilegios
Role Based Acces Control, es una evolución introducida en Solaris 8 -hace ya tiempo- para poder gestionar las acciones mediante privilegios. De esta forma, podemos tener un grupo de privilegios para nuestros operadores nivel 1, para que puedan iniciar/detener/checkear el Sistema de monitorización de Nagios, pero que no puedan hacer un reboot de la máquina. Para solucionar este problema, se introdujeron los privilegios y los roles.
  • Un privilegio es una definición booleana que permite a un usuario no privilegiadoejecutar una acción o no, por ejemplo, uso de puertos privilegiados, cambiar planificador, etc.
  • Un role es una agrupación de privilegios que un usuario puede tomar -si tiene permisos y conoce su contraseña-.
Uso de Roles
La gestión de roles se realiza con los comandos: roleadd, rolemod y roledel. Éstos tienen el mismo formato que la gestión de usuarios (useradd, usermod y userdel) y en el modelo SuperUser, son representados como un usuario, y por lo tanto, podemos utilizar los comandos <passwd> para cambiar la contraseña y <su> para asumir una role.

Una nota importante es que una role siempre tiene como shell a pfsh. Por ejemplo, vamos a ver cómo podemos crear un role de una forma sencilla:

roleadd -d /export/home/testrole -m testrole
64 bloques
# passwd testrole
Nueva contraseña:
Vuelva a escribir la nueva contraseña:
passwd: la contraseña se ha cambiado para testrole satisfactoriamente
su - testrole
echo $SHELL
/bin/pfsh
Administrar los Privilegios
Para las tareas de administración, disponemos del comando <ppriv> que nos permite ver o modificar los valores de los privilegios o atributos. Por ejemplo, para ver el conjunto de privilegios de nuestro proceso shell haremos lo siguiente:

ppriv $$
1046:    -pfsh
flags = 
    E: basic
    I: basic
    P: basic
    L: basic,contract_event,contract_observer,file_chown,file_chown_self,file_dac_execute,file_dac_read,file_dac_search,file_dac_write,file_owner,file_setid,ipc_dac_read,ipc_dac_write,ipc_owner,net_bindmlp,net_icmpaccess,net_mac_aware,net_privaddr,net_rawaccess,proc_audit,proc_chroot,proc_lock_memory,proc_owner,proc_setid,proc_taskid,sys_acct,sys_admin,sys_audit,sys_ip_config,sys_mount,sys_nfs,sys_resource
La salida de este comando nos proporciona los siguientes datos:
  • Heredados (I): Privilegios heredados en exec
  • Permitidos (P): Privilegios máximos del proceso
  • Efectivos (E): Privilegios actualmente activos, es un subconjunto de (P)
  • Limite (L): Privilegios máximos que un proceso y sus hijos pueden llegar a obtener en el siguiente exec

Privilegios en Solaris
Todos los procesos tienen asociados unos privilegios -como vimos en la primera parte- Efectivos (E) que el kernel evaluará antes de ejecutarlo.

Solaris incorpora alrededor de 70 privilegios definidos en varios grupos,  identificados comogrupo_nombre_privilegio, por ejemplo:
  • FILE: Privilegios de gestión de archivos en sistemas de archivos.
  • IPC: Privilegios de gestión y acceso a objetos IPC
  • NET: Privilegios de gestión y acceso a funcionalidades de red
  • PROC: Privilegios de gestión y acceso a las propiedades restrigidas de los procesos
  • SYS: Privilegios de acceso sin restricciones a varias propiedades de sistema
Gestión Básica de Privilegios
Como ya comentamos en la primera parte, para ver los privilegios de un proceso debemos utilizar el comando <ppriv _pid_>, sin embargo, en esta ocasión vamos a utilizar la opción <-l> que nos mostrará los todos los permisos actuales, por ejemplo:
ppriv -l|wc -l
      68
ppriv -l|head -4
contract_event
contract_observer
cpc_cpu
dtrace_kernel
Roles y Usuarios
El uso de privilegios está indicado principalmente a ser asignados a roles, donde definiremos conjuntos de acciones que puede definir un grupo. Esta definición la llamaremos role, así mismo, un role puede ser adquirido por diferentes usuarios.

Entraremos en más detalle del uso de roles en las siguientes entregas, no te preocupes que poco a poco iremos montando el rompecabezas ...

Añadir Privilegios a un usuarios
Podemos añadir privilegios a un usuario en concreto, es decir, sin tener que utilizar roles. Esto se utiliza principalmente para demonios y/o situaciones muy concretas, para el resto es mejor -y más fácil- utilizar roles.

Para añadir un privilegio a un usuario, utilizaremos el comando <usermod> con la opción <-K> donde asignaremos los privilegios separados por coma, el formato es el siguiente:
# usermod -K defaultpriv=privilege_1,privilege_2,privilege_username
Por ejemplo, para asignarle privilegios al usuario test con la finalidad de que sea capáz de sincronizar el reloj utilizando el comando <ntpdate> vamos a asignar los privilegios: sys_time(para la hora) y net_privaddr (para poder hacer bind en un puerto inferior a 1024).

Primero comprobaremos los permisos del usuario, posteriormente asignaremos los privilegios y volveremos a probar, vemos el ejemplo:
ppriv $$
14617:  -bash
flags = 
        E: basic
        I: basic
        P: basic
        L: basic,contract_event,contract_observer,file_chown,file_chown_self,file_dac_execute,

file_dac_read,file_dac_search,file_dac_write,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_bindmlp,net_icmpaccess,net_mac_aware,net_privaddr,
proc_audit,proc_chroot,proc_lock_memory,proc_owner,proc_priocntl,proc_setid,
proc_taskid,sys_acct,sys_admin,sys_audit,sys_mount,sys_nfs,sys_resource,sys_time
$ /usr/sbin/ntpdate hora.rediris.es
 7 Sep 23:52:27 ntpdate[14631]: bind() fails: Permission denied
exit
logout
usermod -K defaultpriv=basic,sys_time,net_privaddr test
UX: usermod: test is currently logged in, some changes may not take effect until next login.
# su - test
Sun Microsystems Inc.   SunOS 5.10      Generic January 2005
/usr/sbin/ntpdate hora.rediris.es
 7 Sep 23:52:42 ntpdate[14647]: adjust time server 130.206.3.166 offset -0.002587 sec
ppriv $$
14643:  -bash
flags = 
        E: basic,net_privaddr,sys_time
        I: basic,net_privaddr,sys_time
        P: basic,net_privaddr,sys_time
        L: basic,contract_event,contract_observer,file_chown,file_chown_self,file_dac_execute,

file_dac_read,file_dac_search,file_dac_write,file_owner,file_setid,ipc_dac_read,
ipc_dac_write,ipc_owner,net_bindmlp,net_icmpaccess,net_mac_aware,net_privaddr,
proc_audit,proc_chroot,proc_lock_memory,proc_owner,proc_priocntl,proc_setid,
proc_taskid,sys_acct,sys_admin,sys_audit,sys_mount,sys_nfs,sys_resource,sys_time
Qué es un rol
Un rol es gan parte similar a un usuario con la diferencia que no es posible iniciar una sessión con él. Me explico, imaginemos que tenemos un rol llamado postgres, si quieramos iniciar sessión con él, el sistema nos mostraría el siguiente error:
console login: postgres
Password: ********
Roles can oly be assume by authorized users
Login incorrect
Analizando el error, nos informa que sólo una vez en el sistema,  podemos asumir el rol si estamos autorizados. Es aquí donde encontramos las diferencias.

Relamente Necesito Roles
Buena pregunta, yo tardé unos meses en ver que sí, pero hasta entonces no lo tenía muy claro. Cuando llevaba unos meses adminstrando Solaris -allá por el Solaris 8- descubrí una funcionalidad que venía de Trusted Solaris, los Roles. Al principio, no veía por qué tenía que ir "asumiendo" un Rol u otro en función de qué tarea quisiera hacer, así que al final decidí volver a mi tradicional "su -" y realizarlo con root.

Un día, cuando ya no era yo sólo el que administraba los Solaris, me encontré con "un toquecito en la espalda diciéndome: es que ... no sé ... pero ....  el servidor de correo no funciona ... y yo no he tocado nada"

Aquí empezaron mis problemas ... ya que root tiene el control de todo, pero .. quién controla aroot? Y más importante: Qué "root" ha sido?

Si analizamos los registros de auditoria, vemos que el comando lo ha ejecutado "root", pero si tenemos varios SysAdmin, quién ha sido? Si, es cierto, el comando "su" se registra pero ... quién lo ha ejecutado?
tail /var/adm/sulog 
SU 09/26 13:07 + pts/5 itily-root
SU 09/26 13:10 + pts/6 zooey-root
Bien, es cierto que podemos habilitar la auditoria -que en aquél entonces no estaba, mal, mal, muy mal- pero ... podemos hacer algo más?

La respuesta es SI, activar los roles. 


Modelo de Seguridad utilizando Roles
El uso de <roles> dentro de un sistema de seguridad hace posible el concepto de <Administración Delegada>, es decir, imaginemos que tenemos varios perfiles de administradores, unos Junior otros Senior, incluso gente que no sabe Solaris.  Podemos pensar de forma rápida en entregar la contraseña de root al administrador Senior, y para los otros solicitar que la introduzca cuando sea necesario.

Bien, a priori puede parecer que con esto hemos solventado el problema de nuestro administrador Junior pero qué sucede cuando no encuentra al administrador Senior? O, mejor aún, qué hace el administrador Senior mientras el Junior administra con root?

Como véis, esto no es operativo, y al final, en el modelo de SuperUser sólo podemos entregar la contraseña de root a los adminstradores Senior y Junior, y establecer algún mecanismo mediante "sudo" o "setuid script" para las tareas importantes.

Si, es cierto, podemos utilizar "sudo" que nos permite ejecutar un comando como root aun no siendo, pero ... si ese comando es gestionar PostgreSQL mediante Solaris SMF. Bueno, aquí la cosa se complica.

Divide y Vencerás
Continuando con nuestro ejemplo de PostgreSQL, podemos definir diferentes tareas y cada una de esas tareas asignarlas a diferentes roles, que, a su vez, asignarlas a diferentes usuarios. Me explico, por ejemplo, definimos las tareas de "Administración de PostgreSQL", "Administración de Tomcat" y "Administración Host".

De esta forma, podemos tener la siguiente tabla:
  • Administración PostgreSQL: Iniciar y Detener el Servicio, y ejecutar los comandos de PostgreSQL, pero no configurarlo
  • Adminstración Tomcat: Iniciar y Detener el Servicio, pero no configurarlo
  • Administración Host: Puede realizar cualquier acción
Como ya comentábamos en Instalar PostgreSQL en OpenIndiana, en Solaris existe ya un <rol> para PostgreSQL llamado <postgres>, podemos comprobarlo si ejecutamos el siguiente comando:
itily@openzooey:~$ pfexec cat /etc/user_attr | grep postgres
postgres::::type=role;profiles=Postgres Administration,All
Si nos fijamos en el tipo <type> vemos que pone <role>, si no os aparece ninguna entrada, es que habéis eliminado el role. Por el momento, no vamos a hacer caso al valor de <profiles> ya que lo examinaremos en las siguientes entregas.

Cómo Crear un Role
Como ya hemos comentado, un role es prácticamente un usuario, y por lo tanto, su forma de crearlo es muy parecida. En vez de utilizar <useradd>, utilizaremos <roleadd> con los mismos parámetros a excepción de <-s< que en vez de <bash, sh, csh> serán <pfbash, pfsh, pfcsh>, veámos un ejemplo

root@openzooey:~# roleadd -s /usr/bin/pfbash -d /export/home/asengine -m asengine
80 blocks
root@openzooey:~# passwd asengine
New Password:
Re-enter new Password:
passwd: password successfully changed for asengine
A continuación debemos asignarle nuestro role a un usuario, en nuestro caso, será a <zooey>
root@openzooey:~# usermod -R asengine zooey
Si nos logeamos con este usuario, podremos ver los <roles> que tiene asignados, utilizando el comando <roles>
root@openzooey:~# su - zooey
OpenIndiana     SunOS 5.11      oi_147  September 2010
zooey@openzooey:~$ roles
asengine
zooey@openzooey:~$ su - asengine
Password:
OpenIndiana     SunOS 5.11      oi_147  September 2010
asengine@openzooey:~$ id
uid=102(asengine) gid=1(other) groups=1(other)
Como véis, no ha sido difícil, verdad? Además, como hemos comentado muchas veces, un <rol> es similar a un usuario, por lo tanto, puedo utilizar los comando <chmod, passwd> para asignar los permisos de forma correcta, por ejemplo:
root@openzooey:~# mkdir -p /var/sfchildren
root@openzooey:~# chown -R asengine /var/sfchildren
root@openzooey:~# chmod 700 /var/sfchildren

Cuidado con la asignación de Roles
Debéis tener cuidado con el comando <usermod -R ...> ya que este sustituye no añade roles, es decir, si tenemos el siguiente usuario
root@openzooey:~# roles zooey
root
Y ejecutamos el comando <usermod -R asengine> 
root@openzooey:~# usermod -R asengine zooey
El resultado será que hemos perdido el <role> root y en OpenIndiana tendremos un problema, ya que el usuario <root> es un <role> y por lo tanto, no podremos logearnos desde la consola, ya que ahora el usuario <itily> tiene asignado el <rol>asengine> sólamente,
root@openzooey:~# roles zooey
asengine

Para ello, debemos utilizar el comando <usermod -R role1,role2,role...>
root@openzooey:~# usermod -R root,asengine zooey
root@openzooey:~# roles zooey
root,asengine

Jugando con los Roles
Veamos un poco como podemos utilizar los roles de nuestro ejemplo. En este caso, el usuario <zooey> tendrá asignado el <rol> de <postgres> y por lo tanto, podrá ejecutar sus comandos, sin embargo, no podrá administrar nuestro host.
zooey@openzooey:~$ id
uid=102(zooey) gid=14(sysadmin) groups=14(sysadmin)
zooey@openzooey:~$ roles
postgres
zooey@openzooey:~$ su - postgres
Password:
OpenIndiana     SunOS 5.11      oi_147  September 2010
postgres@openzooey:~$ /u01/app/postgres/9.0/db/bin/64/psql -U postgres   
psql (9.0.0)
Type "help" for help.

postgres=# \q
zooey@openzooey:~$ su -
Password:
Roles can only be assumed by authorized users
su: Sorry
Como hemos comentado, aunque <zooey> conozca la contraseña de <root> no puede asumirla, ya que su usuario no tiene el derecho para hacerlo.

Qué hemos conseguido
Al utilizar roles, hemos conseguido por un lado, tener controlado el acceso, ya que, ahora podemos asignar el role <postgres> a los usuarios que queremos que tengan la posibilidad de administración.

Además, en el supuesto de "alguien" descubra la contraseña del role <postgres> también necesitará conocer el login y password de un usuario con posibilidad de asumirlo.


Qué son las Autorizaciones
Una autorización es un privilegio discreto que puede ser asignado a un usuario o un rol, dicho de otro modo, es un privilegio que nosotros definimos sin que por ello deba ir asignado a un privilegio de UNIX. De esta forma, hacemos que la verificación <UID=0> pase a ser secundaria.

No todos los comandos de Solaris aceptan el uso de autorizaciones, actualmente está soportado en:
  • Suite Solaris Management Console 
  • Comandos de administración de Auditoria, como auditconfig y auditreduce 
  • Comandos de administración de Impresión, como lpadmin y lpfilter 
  • Comandos de Jobs, como atatqbatch y crontab 
  • Comandos orientados a dispositivos, como allocatedeallocatelist_devices ycdrw.
Nosotros nos vamos a centrar principalmente en los Comandos de SMC y, sobre todo en SMF. Es decir, vamos a utilizar <autorizaciones> para permitir administrar los servicios gestionados por SMF a un <rol> definido por nosotros.

Formato de una autorización
Las autorizaciones se encuentran definidas en el fichero </etc/security/auth_attr> y tienen el siguiente formato:
prefix.suffix:res1:res2:short desc:long desc:attr
Donde
  • prefix: Identifica el prefijo, por conveniencia las autorizaciones de Sun Solaris comienzan con <solaris.>, para las nuestras debemos utilizar nuestro Dominio de Internet al revés, por ejemplo, <com.sfchildren.>
  • suffix: Sufijo del componente. Cuando una autorización termina con <grant> hacemos que quien posea dicha autorización pueda otorgarla a otros, por ejemplo, teniendo la autorizaciones <solaris.com.sfchildren.asengine.grant y solaris.com.sfchildren.asengine.analyzer>,  si asignamos <solaris.com.sfchildren.asengine.grant>, a un role o usuario, éste podrá asignar la autorización <solaris.com.sfchildren.asengine.analyzer> a otro role o usuario.
  • res1 y res2: Campos reservados
  • short desc: Descripción corta
  • long desc: Descripción larga
  • attr: Definición de atributos con el formato <KEY=VALUE>
Por ejemplo,
solaris.admin.usermgr.pswd:::Change Password::help=AuthUserMgrPswd.html
Ver las autorizaciones asignadas
Para ver las autorizaciones asignadas a un usuario o role, simplemente deberemos ejecutar el comando <auths [nombre]>, dónde nombre será un role o un usuario, si no ponemos nada, entonces nos mostrará las autorizaciones del usuario actual, por ejemplo:
root@openzooey:~# auths 
solaris.*
root@openzooey:~# auths tomcat
solaris.admin.wusb.read,
solaris.device.cdrw,
solaris.device.mount.removable,
solaris.mail.mailq,
solaris.profmgr.read

Asignar una Autorización
Las autorizaciones pueden ser asignadas a roles o usuarios, para ello utilizaremos el comando <rolemod> o <usermod> con la opción <-A autorizacion1, autorizacion2, autorizacion>.

Esta opción sustituye no añade, por lo tanto, si quereis conservar las actuales, debereis incluirlas. Para eliminar las autorizaciones, simplemente utilizamos la opción <-A "">, por ejemplo:
root@openzooey:~# rolemod -A solaris.org.apache.smf.value.tomcat,solaris.org.apache.smf.manage.tomcatroot@openzooey:~# auths tomcat
solaris.org.apache.smf.manage.tomcat,
solaris.org.apache.smf.value.tomcat,
solaris.admin.wusb.read,
solaris.device.cdrw,
solaris.device.mount.removable,
solaris.mail.mailq,
solaris.profmgr.read

Veamos un Ejemplo Completo
Vamos a partir de Cómo Instalar Apache Tomcat en Solaris utilizando SMF, para realizar algunos cambios en la instalación, uso de roles y autorizaciones.

En ese post -Instalación de Tomcat- creabamos un grupo y usuario llamado <webrunner>, en esta ocasión, vamos a crear el grupo de igual forma, pero en vez de un usuario llamado <webrunner> vamos a crear un <role> llamado <tomcat6>.

Por lo tanto,  tendremos la siguiente estructura de instalación de Apache Tomcat
  • TOMCAT_HOME: /opt/www/tomcat6
  • JAVA_HOME: /usr/java
  • TOMCAT_USER: tomcat6
  • TOMCAT_GROUP: webrunner
  • PROJECT_NAME: tomcat6
Creación del Grupo, Project y Role
Como hemos hecho en otras ocasiones, crearemos un grupo, projecto y un role para nuestra instalación 
groupadd webrunner
# roleadd -s /bin/pfbash -d /export/home/tomcat6 -m -g webrunner tomcat6
# projadd -c 'Tomcat6 Project' -G webrunner -U tomcat6 tomcat6
# passwd tomcat6
New Password:  *********
Re-enter new Password:  *********
passwd: password successfully changed for tomcat6


Creación de las Autorizaciones
Vamos a crear las autorizaciones necesarias para la gestión de nuestro servicio Apache Tomcat desde Solaris SMF, para ello, definiremos una para <gestión>, otra para <cambio> y por último nuestro <grant>

Dentro de Solaris SMF, debemos asignar una autorización para la propiedad <action> que nos permitirá gestionar los servicios, y la propiedad <value> para cambiar los valores. Básicamente, si tenemos sólo la autorización para <action> podremos activar/desactivar los servicios, pero "de forma temporal" -es decir utilizando la opción <-t>- ya que no tenemos la autorización <value> para "guardar el cambio" 
echo "solaris.org.apache.smf.value.tomcat:::Change value of Apache Tomcat::" >> /etc/security/auth_attr
echo "solaris.org.apache.smf.manage.tomcat:::Manage Apache Tomcat service states::" >> /etc/security/auth_attr
La estructura de la autorización utilizada es solaris.org.apache.smf., por un tema decompatibilidad, pero podíamos haber puesto cualquier cadena, por ejemplo, solaris.org.apache.tomcat6.administrar

Modificación del Manifest
A continuación editaremos nuestro archivo Manifest para Apache Tomcat 6, o bien, podéis bajaros la versión modificada para Apache Tomcat 6 con Autorizaciones de Solaris. Y, aunque el method no ha sido modificado, podéis descargarlo desde Apache Tomcat Method for Solaris SMF

En las sección general añadiremos las siguientes propiedades: 
        <property_group name='general' type='framework'>
                <propval
                     name='value_authorization'
                     type='astring'
                    value='solaris.org.apache.smf.value.tomcat' />
                <propval
                    name='action_authorization'
                    type='astring'
                    value='solaris.org.apache.smf.manage.tomcat' />
        </property_group>
Y dentro de nuestra instancia, añadiremos una propiedad llamada <value_authorization> para definir el valor de la autorización. 
   <property_group name='tomcat_6' type='application'>
                        <propval name='home' type='astring'
                           value='/opt/www/tomcat-6.0' />
                        <propval name='jvmargs' type='astring'
                           value='-d32 -Xms64m -Xmx128m' />
                        <propval name='project' type='astring'
                           value='tomcat6' />
                        <propval name='java_home' type='astring'
                           value='/usr/java' />
             <propval name='value_authorization' type='astring'
                           value='solaris.org.apache.smf.value.tomcat' />

   </property_group>

Cargar el Nuevo Manifest de Apache Tomcat
Si habéis decidido descargar el nuevo Manifest para Apache Tomcat 6 utilizando Autorizaciones, simplemente deberemos utilizar <wget> y volverlo a cargar. Si, por el contrario lo habéis modificado, sólo será necesario recargarlo con <svccfg>
root@openzooey:/# mkdir -p /var/svc/manifest/application/web/
root@openzooey:/# cd /var/svc/manifest/application/web
root@openzooey:/var/svc/manifest/application/web# wget http://blog.sfchildren.com/blogger/tomcat-roles/smf/tomcat_6.xml
root@openzooey:/var/svc/manifest/application/web# svccfg 
svc:> validate tomcat_6.xml 
svc:> import tomcat_6.xml 
svc:> quit
root@openzooey:/var/svc/manifest/application/web# svcs tomcat_6
STATE          STIME    FMRI
disabled       16:17:08 svc:/application/web/tomcat_6:default_32bits
disabled       16:17:08 svc:/application/web/tomcat_6:default_64bits

Asignar las Autorizaciones
Por último, vamos a asignar las autorizaciones a un usuario que será el encargado de gestionar el servicio, pero no de configurarlo, en nuestro caso, será <webope>
$ id
uid=108(webope) gid=100(webope)
auths
solaris.admin.wusb.read,
solaris.device.cdrw,
solaris.device.mount.removable,
solaris.mail.mailq,
solaris.profmgr.read
Si intentamos activar el servicio <tomcat_6:default_64bits> con el usuario <webope> antes de asignar las autorizaciones, veremos el siguiente error:
webope@openzooey:~$ svcadm enable tomcat_6:default_64bits
svcadm: svc:/application/web/tomcat_6:default_64bits: Permission denied.
Bien, ahora asignaremos las autorizaciones y volveremos a repetir el comando de activación.
root@openzooey:/# usermod -A solaris.org.apache.smf.manage.tomcat,solaris.org.apache.smf.value.tomcat webope
root@openzooey:/# su - webope
OpenIndiana    SunOS 5.11    oi_147    September 2010
webope@openzooey:~$ svcadm enable tomcat_6:default_64bits
webope@openzooey:~$ svcs tomcat_6:default_64bits
STATE          STIME    FMRI
online    16:47:42 svc:/application/web/tomcat_6:default_64bits
Y también podemos desactivar el servicio, utilizando la opción <disable>
webope@openzooey:~$ svcadm disable tomcat_6:default_64bits
webope@openzooey:~$ svcs tomcat_6:default_64bits
STATE          STIME    FMRI
disabled       16:48:40 svc:/application/web/tomcat_6:default_64bits
Conclusiones
Espero que con este ejemplo completo de uso de autorizaciones aplicado al servicio SMF, podáis utilizar un elemento muy interesante en cuanto a sistemas de seguridad granulados.

Tal vez alguno se cuestione el por qué asignar las autorizaciones a un usuario (o role) que no tiene permisos de configuración pero si de inicio y parada, parece una tontería, no? Bueno, la verdad es que si pensamos en sistemas autónomos de monitorización, como por ejemplo, Nagios para Solaris 10, entenderemos que podemos configurar una acción para el estado MAINTANCEque llame a un script que haga un refresh del servicio.

Es cierto que podemos utilizar el usuario del servicio -en nuestro caso tomcat6- pero, si alguien tomase el control de nuestra máquina "nagios" puede hacer mucho daño ...

Además, de esta forma, podemos tener separado el rol de cada uno de nuestros empleados, por ejemplo, Administradores de Sistemas de Operadores, y por lo tanto, dejar a un Operador que haga un "refresh" pero no un "stop" del servicio.


Que es <pfexec>
Podemos definir <pfexec> como una versión mejorada del comando <sudo>, el cual nos permite ejecutar comandos con unos privilegios diferentes a los que el usuario logeado tiene. Por ejemplo, podemos ejecutar un comando como si de <root> se tratase, o como otro.

<pfexec> nos permite asignar un grupo de propiedades como: uid, gid, euid, privileges, etc. De esta forma, podemos crear una forma sencilla de acceder a comando privilegiados por cuentas que no lo son.

La base de datos de <pfexec>
La definición de los comandos y sus opciones se encuentra en el archivo </etc/security/exec_attr> y su formato es el siguiente:
name:policy:type:res1:res2:id:attr
Donde
  • name, hace referencia al nombre de la política. Distingue entre mayúsculas y minúsculas
  • policy, hace referencia al tipo de política, puede tener los valores: suser o solaris. En versiones anteriores a Solaris 10, siempre era suser (Standar Solaris User), sin embargo, a partir de Solaris 10 se introdujo <solaris> que nos permite asignar <privileges>, cosa que con %lt;suser> no es posible. Además, <suser> es un subconjunto de <solaris>, por lo tanto, yo os recomiendo utilizar siempre <solaris> si utilizais la versión 10 o superior.
  •  type, hace referencia al tipo, donde puede tener los valores: act o cmd. El valor de <act> se utiliza cuando tenemos configurado <Trusted Extensions> y hace referencia a una acción de CDE. Si utilizamos el valor <cmd> hace referencia a un comando <shell>.
  • res1 y res2, están reservados para futuros usos
  • id, texto que identifica de forma única el objeto, es decir, si hemos definido <type> como <cmd>, entonces será el "full path" al comando. Podemos utilizar el "*" si queremos indicar "cualquier comando", por ejemplo, si queremos permitir la ejecución de todos los comandos de <sbin> del servidor de DHCP, pondremos <$DHCP_HOME/sbin/*>.
  • attr, son los atributos que quiero asignar a la política donde serán: euid,  uid,  egidgidprivs y limitprivs.
Por ejemplo, tenemos la siguiente entrada en la base de datos sobre el uso del comando <pfiles>
Process Management:solaris:cmd:::/usr/bin/pfiles:privs=proc_owner
Esta entrada, nos permitirá ejecutar el comando <pfiles> como utilizamos el <privilegio> >proc_owner> estaremos permitiendo enviar señales a otros procesos, a excepción de que tengan el uid=0.

Esto es un tema importante, es decir, si utilizamos el attr:uid=0, estaremos ejecutando el comando como <root>, sin embargo, al utilizar attr:privs=proc_owner, estamos diciendo que el comando se ejecuta con el uid del usuario, pero le concedemos el privilegio de enviar señales a los demás procesos siempre que no sean de <root&gt.  Esto lo explicaremos en el ejemplo, no os preocupeis.

Crear una nueva Política
El uso de <pfexec> está unido a las políticas, es decir, en la base de datos </etc/security/exec_attr> se encuentran "los detalles", sin embargo, la definición de una política se encuentra en </etc/security/prof_attr>, por lo tanto, para crear una nueva política deberemos definir primero la política en la base de datos </etc/security/prof_attr> y posteriormente añadir los comandos -o definición de la política- en la base de datos </etc/security/exec_attr>.

Por ejemplo, imaginemos que queremos crear una política nueva llamada <My Process Management> y queremos que esta política pueda ejecutar el comando </usr/bin/pfiles> con un <uid=0>, entonces haremos lo siguiente:

root@openzooey:/# echo "My Process Management:::Custom Process Management with UID to 0:help=RtProcessManage.html" >> /etc/security/prof_attr
root@openzooey:/# echo "My Process Management:solaris:cmd:::/usr/bin/pfiles:uid=0" >> /etc/security/exec_attr
De esta forma hemos creado una nueva política y hemos asignado unos atributos de ejecución.

Asignar una Política
La asignación de una política se realiza con el comando <rolemod> -si es un <role>- o &usermod> -si es un usuario- y la opción <-P '_policy_name1, _policy_name2, ...'>, por ejemplo:
root@openzooey:/# rolemod -P 'Process Management,Network Management' tomcat6
Podemos comprobar cómo se han añadido las nuevas políticas a nuestra base de datos de usuarios en </etc/user_attr>, por ejemplo,
root@openzooey:/# cat /etc/user_attr|grep tomcat6
tomcat6::::type=role;profiles=Process Management,Network Management
Eliminar una Política
Para eliminar una política, deberemos asignar una política vacía <-P ''>, es decir,
root@openzooey:/# rolemod -P '' tomcat6
root@openzooey:/# cat /etc/user_attr|grep tomcat6
tomcat6::::type=role

Ver los profiles asginados a un <role> o <user>
Para ver los profiles asignados utilizaremos el comando <profiles> y el nombre de usuario o role que queremos verificar, por ejemplo, si queremos ver los roles asignados al role <tomcat6> haremos lo siguiente:
root@openzooey:/# profiles tomcat6
tomcat6:
          Basic Solaris User
          All
Podemos utilizar el comando <-l> para ver de forma extendida la información, por ejemplo:

root@openzooey:/# profiles -l tomcat6
tomcat6:
      Basic Solaris User
          /usr/bin/cdda2wav.bin      privs=file_dac_read,sys_devices,proc_priocntl,net_privaddr
          /usr/bin/cdrecord.bin      privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
          /usr/bin/readcd.bin        privs=file_dac_read,sys_devices,net_privaddr
      All
          *
Un Ejemplo Completo
Tenemos un <role> llamado <tomcat6> y queremos permitirle ver/modificar procesos del sistema. Para ello, hemos decidido añadirle la política <Process Management> que se encuentra ya definida en Solaris.

Esta política <Process Management> utiliza privilegios en vez de uid, por lo tanto, nos permitirá ver/modificar todos los procesos menos los que tengan uid=0 -es decir, de root-.

Lo primero que vamos a hacer es comprobar que <tomcat6> no tiene privilegios para modificar la prioridad del proceso <rcpbind> y luego asignaremos el <profile> "Process Management" para ver qué sucede:
root@openzooey:/# profiles tomcat6
tomcat6:
          Basic Solaris User
          All
root@openzooey:/# su - tomcat6
OpenIndiana     SunOS 5.11      oi_147  September 2010
tomcat6@openzooey:~$ ps -o pri,user,pid,nice,args -p 665
PRI     USER   PID NI COMMAND
 59   daemon   665  0 /usr/sbin/rpcbind
tomcat6@openzooey:~$ renice 10 665
renice: 665:setpriority: Not owner
Obviamente, Solaris no ha permitido a <tomcat6> modificar la prioridad del proceso porque no es su propietario, sin embargo, si asignamos el profile <Process Management>, veremos qué sucede,
root@openzooey:/# rolemod -P 'Process Management' tomcat6
root@openzooey:/# profiles tomcat6
tomcat6:
          Process Management
          Basic Solaris User
          All
root@openzooey:/# su - tomcat6
OpenIndiana     SunOS 5.11      oi_147  September 2010
tomcat6@openzooey:~$ ps -o pri,user,pid,nice,args -p 665
PRI     USER   PID NI COMMAND
 59   daemon   665  1 /usr/sbin/rpcbind
tomcat6@openzooey:~$ renice +19 665
tomcat6@openzooey:~$ ps -o pri,user,pid,nice,args -p 665
PRI     USER   PID NI COMMAND
 59   daemon   665 39 /usr/sbin/rpcbind
En esta ocasión hemos podido moficar el <nice> del proceso -aún cuando no es nuestro-, además este <profile> nos permite examinar los procesos aunque no sean nuestros -recordar lo que hemos hablado al principio sobre los privilegios priv=proc_owner-, vamos a verlo con detalle.

Ahora lo que vamos a utilizar el el comando <pfiles> para examinar los archivos abiertos de un proceso, para ello, vamos a examinar el proceso de <prostgres>
tomcat6@openzooey:~$ ps -o pri,user,pid,nice,args -p 614
PRI     USER   PID NI COMMAND
 59 postgres   614 20 /u01/app/postgres/9.0/db/bin/64/postgres -D /var/postgres/9.0/data
tomcat6@openzooey:~$ pfiles 614
614:    /u01/app/postgres/9.0/db/bin/64/postgres -D /var/postgres/9.0/data
  Current rlimit: 256 file descriptors
   0: S_IFCHR mode:0666 dev:524,0 ino:19922952 uid:0 gid:3 rdev:38,2
      O_RDONLY|O_LARGEFILE
      /devices/pseudo/mm@0:null
      offset:0
   1: S_IFREG mode:0600 dev:90,65538 ino:149346 uid:90 gid:90 size:156012
      O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE
      /var/log/postgres/server.log
      offset:156012
   2: S_IFREG mode:0600 dev:90,65538 ino:149346 uid:90 gid:90 size:156012
      O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE
      /var/log/postgres/server.log
      offset:156012
   3: S_IFDOOR mode:0444 dev:534,0 ino:47 uid:0 gid:0 size:0
      O_RDONLY|O_LARGEFILE FD_CLOEXEC  door to nscd[462]
      /var/run/name_service_door
   7: S_IFSOCK mode:0666 dev:533,0 ino:45078 uid:0 gid:0 size:0
      O_RDWR|O_NONBLOCK
        SOCK_DGRAM
        SO_DGRAM_ERRIND,SO_SNDBUF(57344),SO_RCVBUF(57344)
        sockname: AF_INET6 ::1  port: 59936
        peername: AF_INET6 ::1  port: 59936
Sin embargo, si ahora hacemos lo mismo sobre un proceso con uid=0, por ejemplo <nscd> veremos qué sucede
tomcat6@openzooey:~$ ps -ef|grep nscd|grep -v grep
    root   462     1   0 11:29:37 ?           0:09 /usr/sbin/nscd
tomcat6@openzooey:~$ pfiles 462
pfiles: permission denied: 462
Oops! Acceso denegado! Si, esto es debido al uso de privilegios y no <uid=0>. Esta es una gran diferencia con <sudo> ya que nos permite tener una definición mayor y más segura.

Cómo puedo hacer que se comporte como <sudo>
Bien, en nuestro ejemplo de Cómo crear una nueva política, hemos definido <My Process Management> donde permitíamos ejecutar el comando </usr/bin/pfiles> con el atributo <uid=0>, vamos a asignar este <profile> a nuestro usuario <tomcat6> y volveremos a comprobar su salida.

root@openzooey:/# rolemod -P 'My Process Management' tomcat6
root@openzooey:/# profiles -l tomcat6
tomcat6:
      My Process Management
          /usr/bin/pfiles            uid=0
      Basic Solaris User
          /usr/bin/cdda2wav.bin      privs=file_dac_read,sys_devices,proc_priocntl,net_privaddr
          /usr/bin/cdrecord.bin      privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
          /usr/bin/readcd.bin        privs=file_dac_read,sys_devices,net_privaddr
      All
          *
root@openzooey:/# su - tomcat6
OpenIndiana     SunOS 5.11      oi_147  September 2010
tomcat6@openzooey:~$ ps -ef|grep nscd|grep -v grep
    root   462     1   0 11:29:37 ?           0:09 /usr/sbin/nscd
tomcat6@openzooey:~$ pfiles 462
462:    /usr/sbin/nscd
  Current rlimit: unlimited file descriptors
   0: S_IFCHR mode:0666 dev:524,0 ino:19922952 uid:0 gid:3 rdev:38,2
      O_RDWR
      /devices/pseudo/mm@0:null
      offset:0
   1: S_IFCHR mode:0666 dev:524,0 ino:19922952 uid:0 gid:3 rdev:38,2
      O_RDWR
      /devices/pseudo/mm@0:null
      offset:0
   2: S_IFCHR mode:0666 dev:524,0 ino:19922952 uid:0 gid:3 rdev:38,2
      O_RDWR
      /devices/pseudo/mm@0:null
      offset:0
   3: S_IFDOOR mode:0777 dev:527,0 ino:0 uid:0 gid:0 size:0
      O_RDWR FD_CLOEXEC  door to nscd[462]
   4: S_IFSOCK mode:0666 dev:533,0 ino:23670 uid:0 gid:0 size:0
      O_RDWR
        SOCK_RAW
        SO_SNDBUF(8192),SO_RCVBUF(8192)
        sockname: AF_ROUTE
        peername: AF_ROUTE
En esta ocasión sí que Solaris nos ha permitido ver los archivos abiertos de <nscd> porque hemos utilizado <uid=0> en los atributos, haciendo que se ejecute como <root>, por lo tanto, no hay limitaciones.

Cuando debo utilizar <pfexec _comando_> y cuando no
Lo cierto es que ya hemos hablado de esto en la entrega dedicada a los Roles en RBAC, Roles y Seguridas Parte 5 pero para hacer un breve resumen os diré
  • Hay que utilizar <pfexec _comando_> cuando queramos lanzarlo desde un <usuario>, ya que la <shell> de un usuario no es <pfXYZ>.
  • Si lanzamos el comando desde un <role>, no es necesario, ya tenemos asignada una <shell> &pfXYZ>, por lo tanto, no es necesario.

Comentarios