# rm-rf.es | Administración de sistemas

Bitácora personal de un SysAdmin Gnu/Linux, Windows, BSD...

Bucle de password expirado en ldap nativo RHEL contra Sun LDAP


Me ha resultado difícil concretar el problema en tan poco espacio en el título. La situación es la siguiente:

  • Sun LDAP Server
  • Cliente Red Hat Enterprise Linux con LDAP nativo configurado contra el servidor de Sun

La configuración del LDAP Nativo en Red Hat es relativamente sencilla, únicamente lanzamos el authconfig-tui o pasamos los parámetros correspondientes al comando authconfig. Una vez configurado, ya deberíamos poder autenticarnos con los usuarios del LDAP.

En este caso concreto, todo funcionaba correctamente a excepción de la autenticación. Si hacíamos su desde root a cualquier usuario del LDAP funcionaba, la salida del comando getent passwd o getent shadow mostraba todos los usuarios, podíamos hacer ldapsearch, etc.

Con la autenticación, nos pedía continuamente cambiar la password porque había expirado:

$ ssh test@10.0.0.15
You are required to change your LDAP password immediately.
Warning: Your password has expired, please change it now
...
...

Por lo que sea, los servidores Solaris en nuestro caso hacían caso omiso a los atributos de expiración, llevabamos años sin problemas, pero RHEL sí que los revisaba. Todo debería haber funcionado una vez cambiada la clave, pero los servidores RHEL seguían pidiendo continuamente que se cambiara (en Solaris sí que se accedía con la nueva clave).

Para poder acceder correctamente desde Red Hat (y creo que desde cualquier máquina Linux) hay que prestar especialmente atención a estos atributos de LDAP para cada usuario:

shadowMax:
shadowMin:
shadowWarning:

Si están presentes, es necesario que su valor este vacío (no 0) para solucionar el problema. O eso, o especificar una expiración de 99999 en shadowMax… una vez cambiado accederéis sin problemas vía ssh  y con el resto de autenticación.

Consultar y exportar certificados SSL en Sun Web Server (certutil y pkcs12)


Sun Web Server (en este artículo trabajamos sobre la versión 6.1) almacena los certificados y llaves privadas en ficheros .db (cert8.db y key3.db). Vamos a hacer uso de los comandos certutil y pkcs12 para poder hacer operaciones de listado y exportación de certificados (con o sin private key).

Para listar los certificados que tiene instalados el servidor web debemos usar el comando certutil, que se encuentra en la ruta /bin/https/admin/bin/. Los ficheros .db que comentaba antes se encuentran en la carpeta “alias” por defecto. Podéis copiarlos a una ruta temporal para trabajar con ellos en lugar de directamente en la ruta de producción. Una vez realizado, nos colocamos en esa carpeta y ejecutamos el siguiente comando:

$ certutil -L -d .

    CERTIFICADO-WEB                                                CTu,u,u

Como podéis comprobar, en este servidor web tenemos instalado el certificado CERTIFICADO-WEB. Si queremos exportarlo en formato ASCII sin su private key podemos usar el mismo comando pero especificado el certificado y el parámetro -a (ASCII). En formato binario usamos el parámetro -d (DER):

$ certutil -L -d . -n "CERTIFICADO-WEB" -a
    -----BEGIN CERTIFICATE-----
    MIICTjCCAbAxasdhljkads8akjasdolasdYjEfMB0GA1UEChMWU3Vu
    ...
    ...
    asd3asd23sadasdadsasdasd
    -----END CERTIFICATE-----
$ certutil -L -d . -n "CERTIFICADO-WEB" -d

Finalmente, si lo queremos exportar en formato legible:

$ certutil -L -d . -n "CERTIFICADO-WEB"
     Certificate:
         Data:
             Version: 3 (0x2)
             Serial Number: ...
             Signature Algorithm: PKCS #1 SHA-1 With RSA Encryption
             Issuer:
...
...

En caso de necesitar exportar también la private key del certificado, hacemos uso del comando pkcs12. En este caso necesitaremos la password del “NSS Certificate DB” para poder acceder a los certificados del servidor así como especificar una nueva para el fichero resultante PKCS12. Seguimos ubicados en la carpeta donde están los ficheros *.db. Especificamos el fichero de salida (certificado.p12, y el nombre del certificado.

$ pk12util -o certificado.p12 -n 'CERTIFICADO-WEB' -d .
Enter Password or Pin for "NSS Certificate DB":
Enter password for PKCS12 file:
Re-enter password:
pk12util: PKCS12 EXPORT SUCCESSFUL

Debug de procesos en Solaris con Truss


Podríamos decir que truss es el equivalente en Solaris a strace de Linux, si bien existen también otras alternativas como dtrace que también cumplen perfectamente esta función.

Truss es una utilidad que permite ejecutar el comando especificado o un proceso concreto y muestra durante su ejecución las llamadas al sistema que ejecuta y las señales que recibe. Esto permite ver todo el proceso de ejecución y hacer debug de cualquier error o fault que ocurre.

Vamos a ver unos ejemplos. Lo más básico sería ejecutar truss seguido del comando del que queremos ver su debug, en el siguiente ejemplo simplemente ejecutamos el comando df:

# truss df
execve("/usr/gnu/bin/df", 0x08047E6C, 0x08047E74)  argc = 1
sysinfo(SI_MACHINE, "i86pc", 257)               = 6
mmap(0x00000000, 32, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xD1BB0000
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xD1BA0000
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xD1B90000
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xD1B80000
memcntl(0xD1BB8000, 32064, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
memcntl(0x08050000, 15312, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
resolvepath("/usr/lib/ld.so.1", "/lib/ld.so.1", 1023) = 12
resolvepath("/usr/gnu/bin/df", "/usr/gnu/bin/df", 1023) = 15
sysconfig(_CONFIG_PAGESIZE)                     = 4096
stat64("/usr/gnu/bin/df", 0x08047AB0)           = 0
open("/var/ld/ld.config", O_RDONLY)             Err#2 ENOENT
stat64("/lib/libc.so.1", 0x08047260)            = 0
...
...
...

No muestro todo el output debido a su longitud, podemos volcarlo a un fichero para analizarlo mejor en lugar de la salida stderr:

# truss -o salida.out df

En el siguiente ejemplo hacemos debug de un proceso que ya se encuentra en ejecución:

# truss -rall -wall -f -p <PID>

“-rall” implica ver todos los datos de lectura y “-wall” todos los de escritura, con “-f” vemos los procesos fordked y “-p” especifica el PID.

Podéis ver más ejemplos e información del comando en la página man correspondiente. A continuación podéis ver un par:

$ man truss

Trazar las llamadas de sistema open, close, read y write únicamente:

# truss -t open,close,read,write find . -print >salida.out

Trazar todas las llamads a funciones a nivel de usuario desde y hacia cualquier sitio:

# truss -u a.out -u ld:: -u :: <comando>

Monitorizar Oracle iPlanet Web Server con get-perfdump


Oracle SolarisLa utilidad de monitorización en servidores Web de Sun/Oracle ha mejorado mucho a partir de la versión 7.0. Si bien antes únicamente podíamos acceder a estos datos vía web, ahora podemos hacerlo a través de la shell/CLI wadm, permitiendo acceder a estadísticas a tiempo real de monitorización sin necesidad de hacerlo vía HTTP, con los problemas que conllevaba con el sistema cargado.

La nueva versión, disponible en Sun Java System Web Server, Oracle iPlanet Web Server 7.0 o como lo queráis llamar, añade la posibilidad de ver las Ips y peticiones que se están haciendo a cada instancia y así poder detectar con mayor facilidad el origen de un cuello de botella o sobrecarga del sistema.

Para acceder a wadm nos situamos en la ruta base del servidor web y ejecutamos el siguiente comando indicando usuario y clave de administración:

root@solaris:/opt/oracle/webserver7# ./bin/wadm --user=admin
Indique admin-user-password>
Conexión a localhost:8989
Oracle iPlanet Web Server 7.0.12 B07/01/2011 03:56
wadm>

Una vez dentro, elegimos la instancia y nodo del que queremos ver las estadísticas y tendremos el volcado de información:

wadm> get-perfdump --config solaris --node localhost

La información que recibimos es la siguiente. Tened en cuenta que es un webserver de prueba por lo que no hay apenas información:

wadm> get-perfdump --config solaris --node localhost

Oracle iPlanet Web Server 7.0.12 B07/01/2011 03:56 (SunOS DOMESTIC)

Server started Sat Feb 11 15:24:28 2012
Process 1133 started Sat Feb 11 15:24:29 2012

ConnectionQueue:
-----------------------------------------
Current/Peak/Limit Queue Length            0/4/16384
Total Connections Queued                   20
Average Queue Length (1, 5, 15 minutes)    0,00, 0,00, 0,00
Average Queueing Delay                     10,88 milliseconds

ListenSocket http-listener-1:
------------------------
Address                   https://0.0.0.0:443
Acceptor Threads          1
Default Virtual Server    solaris

ListenSocket http-listener-2:
------------------------
Address                   http://0.0.0.0:80
Acceptor Threads          1
Default Virtual Server    solaris

KeepAliveInfo:
--------------------
KeepAliveCount        6/32768
KeepAliveHits         8
KeepAliveFlushes      0
KeepAliveRefusals     0
KeepAliveTimeouts     6
KeepAliveTimeout      30 seconds

SessionCreationInfo:
------------------------
Active Sessions           0
Keep-Alive Sessions       6
Total Sessions Created    8/129

CacheInfo:
-----------------------
File Cache Enabled       yes
File Cache Entries       14/1024
File Cache Hit Ratio     76/108 ( 70,37%)
Maximum Age              30
Accelerator Entries      0/1024
Acceleratable Requests   18/45 ( 40,00%)
Acceleratable Responses  0/18 (  0,00%)
Accelerator Hit Ratio    0/0 (  0,00%)

Native pools:
----------------------------
NativePool:
Idle/Peak/Limit               1/1/128
Work Queue Length/Peak/Limit  0/0/0

DNSCacheInfo:
------------------
enabled             yes
CacheEntries        0/1024
HitRatio            0/0 (  0,00%)

Async DNS disabled

Performance Counters:
------------------------------------------------
                           Average         Total      Percent

Total number of requests:                     20
Request processing time:    0,0395        0,7899

default-bucket (Default bucket)
Number of Requests:                           20    (100,00%)
Number of Invocations:                       289    (100,00%)
Latency:                    0,0050        0,0999    ( 12,65%)
Function Processing Time:   0,0345        0,6899    ( 87,35%)
Total Response Time:        0,0395        0,7899    (100,00%)

Sessions:
-------------------------------------------------------
Process  Status  Client  Age  VS  Method  URI  Function

Resultan muy interesantes para detectar problemas y optimizar el rendimiento la sección “ConnectionQueue:” y “Sessions:“, en esta última es donde veremos las Ips de acceso, peticiones, URI, etc. Toda la información es bastante descriptiva y comprensible a primera vista. A partir de esta información se pueden generar scripts de recolección de datos, añadir a monitorización tipo Nagios o BigBrother, etc. Los que utilicéis servidores anteriores a la versión 7.0 habréis detectado un gran cambio de la cantidad de información del antiguo perfdump al nuevo.

DB_File.xs:101: db.h: No such file or directory


La situación es la siguiente. Estamos compilando en Solaris 10 el módulo de Perl DB_File. El requerimiento lógico es tener instalado BerkeleyDB en el servidor así que procedemos a ello:

# pkgadd -d db-4.7.25.NC-sol10-x86-local

Ahora procedemos a la típica compilación (Elegir el compilador correcto para Perl en Solaris) y nos encontramos con uno de estos dos errores:

  cc -c -I/usr/local/include -Dbool=char -DHAS_BOOL
  -O2    -DVERSION=\"1.64\" -DXS_VERSION=\"1.64\" -fpic
  -I/usr/local/lib/perl5/i586-linux/5.00404/CORE -DmDB_Prefix_t=size_t
  -DmDB_Hash_t=u_int32_t DB_File.c
  DB_File.xs:101: db.h: No such file or directory
  LD_RUN_PATH="/lib" cc -o blib/arch/auto/DB_File/DB_File.so  -shared
  -L/usr/local/lib DB_File.o    -L/usr/local/lib -ldb
  ld: cannot open -ldb: No such file or directory

Es raro porque el fichero db.h se encuentra en la ruta de instalación de DB. El problema es que el fichero de configuración para la compilación del módulo presupone una ruta estándar que en este caso no se cumple. Así que modificamos dicho fichero de esta forma:

Antes (config.in):

	INCLUDE = /usr/local/BerkeleyDB/include
	LIB     = /usr/local/BerkeleyDB/lib

Por la ruta donde se encuentre, en mi caso /usr/local/BerkeleyDB.4.7/include/db.h:

	INCLUDE = /usr/local/BerkeleyDB.4.7/include
	LIB     = /usr/local/BerkeleyDB.4.7/lib

Y a compilar.

Elegir el compilador correcto para Perl en Solaris


Cuando compilamos módulos de Perl en Solaris (en este caso Solaris 10) hay que tener muy claro el compilador a utilizar. En esta versión de Solaris tenemos por defecto la versión 5.8.4 de Perl, la cual ha sido compilada con la suite de compilación de Sun Studio. La forma habitual de compilar módulos es la siguiente:

# perl Makefile.PL
# make
# make test
# make install

Si lo hacemos así, el sistema utilizará el compilador Sun Studio y habrá flags incompatibles, errores de compilación, etc. Lo que tenemos que hacer es forzar la utilización del compilador GNU C/C++, que por defecto lo encontraremos en /usr/sfw/bin como nos indica el Solaris Install CookBook.

Lo primero que tenemos que hacer es añadir esta ruta al PATH ya que por defecto no está:

export PATH=$PATH:/usr/sfw/bin

Para la ejecución del Makefile.PL utilizaremos perlgcc en lugar de perl a secas, está en la ruta “/usr/perl5/bin/perlgcc“. Para los make forzaremos la utilización de gmake en la ruta anteriormente citada. La lista de comandos sería la siguiente:

# /usr/perl5/bin/perlgcc Makefile.PL
# /usr/sfw/bin/gmake MAKE=/usr/sfw/bin/gmake
# /usr/sfw/bin/gmake MAKE=/usr/sfw/bin/gmake test
# /usr/sfw/bin/gmake MAKE=/usr/sfw/bin/gmake install

Solaris Zones ERROR: the zonepath must be a ZFS dataset


A la hora de crear una zona en Solaris (Solaris Zones|Solaris Containers), es imprescindible que el zonepath, que es el lugar físico en el que se va a alojar sea un sistema de ficheros zfs independiente, también llamado ZFS dataset. En caso contrario recibiremos este error a la hora de instalarla:

ERROR: No zonepath dataset; the zonepath must be a ZFS dataset.

El error es lo suficientemente descriptivo. A la hora de configurar la zona, establecemos el zonepath del siguiente modo dentro del modo de configuración de la zona:

# zonecfg -z zona01
zonecfg:zona01> set zonepath=/ruta/a/la/zona

El paso previo es entonces crear el dataset correspondiente:

# zfs create /rpool/zones
# zfs create /rpool/zones/zona01

Una vez realizado, podemos establecer como zonepath “/rpool/zones/zona01″, verificar la configuración con “verify”, hacer el “commit” e instalar la zona:

# zoneadm -z zona01 install

Introducción a SMF (Service Management Facility) en Solaris


SolarisHace unos días comentaba el paso de System V a Upstart en RHEL y Centos 6. Hoy vamos a hablar sobre Solaris y el cambio introducido a partir de Solaris 9 para la gestión de servicios.

Antes de Solaris 9 los servicios se gestionaban como en la mayoría de sistemas Unix y Linux (legacy), teníamos scripts de arranque en /etc/init.d y se creaban enlaces simbólicos contra ellos en los distintos runlevels (directorios RC) para su arranque/parada. A partir de Solaris 9 se introdujo SMF (Service Management Facility) y se ha convertido en la manera por defecto de gestionar los servicios en Solaris 10.

Los beneficios de SMF sobre el método anterior son sustanciales. Entre ellos la posibilidad de mantener monitorizados los servicios para que en el momento que se produzca una caída levanten de forma instantánea, la gestión inteligente de arranque mediante la cual el servicio tiene unas dependencias y hasta que no estén activas el servicio no está disponible, el arranque en paralelo y de forma asíncrona, etc.

Los comandos básicos para gestion de servicios en SMF son svcs, svccfg y svcadm. Mediante svcs a secas podemos ver el estado de los servicios del sistema (incluidos los del sistema antiguo legacy), a través de distintos parámetros podemos filtrar únicamente los deshabilitados, etc:

# svcs
STATE          STIME    FMRI
legacy_run      9:04:48 lrc:/etc/rc2_d/S20sysetup
legacy_run      9:04:48 lrc:/etc/rc2_d/S47pppd
legacy_run      9:04:49 lrc:/etc/rc2_d/S72autoinstall
legacy_run      9:04:49 lrc:/etc/rc2_d/S73cachefs_daemon
legacy_run      9:04:49 lrc:/etc/rc2_d/S81dodatadm_udaplt
legacy_run      9:04:49 lrc:/etc/rc2_d/S89PRESERVE
disabled        9:02:34 svc:/platform/i86pc/acpihpd:default
online          9:01:28 svc:/system/svc/restarter:default
online          9:01:35 svc:/system/early-manifest-import:default
online          9:01:38 svc:/network/netcfg:default
online          9:01:39 svc:/network/datalink-management:default
online          9:01:39 svc:/network/socket-config:default
...
...

Básicamente vemos el estado del proceso, la última vez que el servicio cambió de estado y su FMRI (Fault Management Resource Identifier). El FMRI es el identificador del servicio. El FMRI se divide en tres partes separadas por “:”. La primera el esquema (svc o lrc según el tipo de servicio), la categoría en la que se encuentra (network, system…) y el nombre del servicio, y finalmente la instancia.

Podemos ver también con detalle el estado de un único servicio con el parámetro “-x” y sus dependencias con “-d”:

# svcs -x  svc:/system/cron:default
svc:/system/cron:default (clock daemon (cron))
 State: online since  1 de noviembre de 2011 09:02:51 WET
   See: cron(1M)
   See: crontab(1)
   See: /var/svc/log/system-cron:default.log
Impact: None.
# svcs -d svc:/system/cron:default
STATE          STIME    FMRI
online          9:02:35 svc:/milestone/name-services:default
online          9:02:49 svc:/system/filesystem/local:default

Podemos verificar rápidamente cómo SMF monitoriza activamente los servicios que están bajo su control, vamos a ver el estado del servicio cron, matarlo con una señal kill y verificar que al momento SMF lo ha levantado de nuevo:

# date
martes  1 de noviembre de 2011 09:46:24 WET
# svcs -v system/cron
STATE          NSTATE        STIME    CTID   FMRI
online         -              9:02:51     62 svc:/system/cron:default
# ps -ef | grep cron
    root   441     1   0 09:02:51 ?           0:00 /usr/sbin/cron
    root   841   687   0 09:46:33 pts/1       0:00 grep cron
# kill 441
# svcs -v system/cron
STATE          NSTATE        STIME    CTID   FMRI
online         -              9:46:38     96 svc:/system/cron:default

A través de svcs también podemos ver el estado de un servicio y diagnosticarlo cuando no es satisfactorio. Encontraremos los siguientes estados: online, offline, disabled, degraded, maintenance y legacy-run. Los cuatro primeros estados están claros, online, offline, deshabilitado y degradado. Cuando un servicio está en estado maintenance es debido a que hay algún problema con el servicio y no puede ser arrancado. Como requiere nuestra intervención se pone a nuestra disposición la ruta hacia el log del servicio para verificar el origen del problema. El estado legacy-run simplemente indica que se trata de un servicio legacy.

Mediante svcadm podemos gestionar el estado de cada uno de los servicios, con los parámetros “enable”, “disable”, “refresh”, “clear”, “mark” y “restart”. Aparte de los obvios, conviene comentar que “refresh” sirve para leer de nuevo los ficheros de configuración del servicio por si se ha realizado algún cambio, “clear” sirve para resetear el servicio si se encuentra en estado de mantenimiento y “mark” para marcar un servicio como degradado, mantenimiento, etc.

Para que veáis un ejemplo de fichero xml básico para un servicio aquí tenéis uno para la gestión de Oracle iPlanet webserver 7 que instalamos hace unos días. Básicamente hemos establecido como dependencias los servicios de red, los sistemas de ficheros locales y el arranque bajo el milestone multi-user (lo que viene siendo el runlevel 3 en legacy). Después establecemos los tres comandos para el arranque, parada y reinicio del servicio:

<?xml version='1.0'?>

<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>

<service_bundle type='manifest' name='webserver7'>

<service name='network/webserver7' type='service' version='0'>
<create_default_instance enabled='true'/>
<single_instance/>
<dependency name='fs' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/system/filesystem/local'/>
</dependency>
<dependency name='net' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/network/physical'/>
</dependency>
<dependent name='webserver7_multi-user' restart_on='none' grouping='optional_all'>
<service_fmri value='svc:/milestone/multi-user'/>
</dependent>
<exec_method name='start' type='method' exec='su www -c "/opt/webserver7/bin/webserver7 start"' timeout_seconds='60'>
<method_context/>
</exec_method>
<exec_method name='stop' type='method' exec='su www -c "/opt/webserver7/bin/webserver7 stop"' timeout_seconds='60'>
<method_context/>
</exec_method>
<exec_method name='restart' type='method' exec='su www -c "/opt/webserver7/bin/webserver7 restart"' timeout_seconds='60'>
<method_context/>
</exec_method>
</service>

</service_bundle>

Para importar un servicio creado de este modo ejecutamos el siguiente comando:

# svccfg import webserver7.xml

Como siempre os recomiendo revisar las páginas man de todos estos comandos para recibir información detallada sobre cada uno de ellos, esto es una pequeña introducción que podría extenderse mucho más si entráramos en detalle de cada una de las características y posibilidades de SMF. Ahí van unas cuantas referencias para aprender más sobre Service Management Facility: