LDAP (parte 5): Importar los usuarios y grupos locales en Ubuntu 14.04 LTS

Publicado por P. Ruiz en

OpenLDAP logo Utilizando el mecanismo que hemos aprendido en los artículos anteriores de esta serie, podríamos crear tantos usuarios como necesitáramos. Incluso podemos crear una nueva cuenta en el servidor OpenLDAP para cada uno de los usuarios y grupos locales que ya tengamos en el equipo que actúa como servidor.

Sin embargo, en este último caso, quizás sea más recomendable automatizar la tarea, escribiendo un pequeño script que obtenga la información que necesite y cree las nuevas cuentas de forma automática. Sobre todo cuando el número de usuarios es muy elevado.

Cómo guarda GNU/Linux la lista de usuarios locales

Para llevar a cabo la tarea de hoy, es importante saber que GNU/LInux, de forma predeterminada, guarda la información sobre los usuarios locales dentro del archivo /etc/passwd.

El archivo /etc/passwd contiene tanto usuarios normales como usuarios especiales del sistema. Para diferenciarlos, los primeros tienen un UID con un valor 1000 o superior.

Por lo tanto, el objetivo general del script será obtener estos datos y crear con ellos un archivo ldif como el que hemos escrito nosotros en el apartado anterior. Después, ejecutará el comando ldapadd para añadirlos.

Para hacernos una idea del trabajo a realizar, debemos estudiar el aspecto general del archivo /etc/passwd, para lo que usaremos la siguiente orden:

cat /etc/passwd

El resultado será similar al de la siguiente imagen:

Salida del comando cat.

En términos generales, observamos que los diferentes datos de cada cuenta van separados por dos puntos (:) y, en particular, los datos contenidos son los siguientes:

  • El nombre de la cuenta (también conocido como login).

  • La contraseña, aunque aparece una x porque en realidad se encuentra en el archivo /etc/shadow (este campo se mantiene por compatibilidad con la estructura original del archivo).

  • El UID de usuario que debe ser un identificador único en el sistema.

  • El GID del grupo primario al que pertenece el usuario. En Ubuntu, de forma predeterminada, cuando creamos un usuario se crea un grupo con el mismo nombre, que actúa como su grupo primario.

  • Información sobre el usuario, separada por comas. El primer dato suele ser su nombre completo.

  • El directorio home del usuario, que suele ser una carpeta con el nombre de la cuenta, dentro de la carpeta /home.

  • La shell que utilizará el usuario de forma predeterminada. Suele ser /bin/bash/.

A partir de aquí, nos pondríamos manos a la obra para escribir el script. Probablemente, cada programador le daría a este problema una solución diferente. Nosotros hemos incluido un posible resultado, donde hemos primado la claridad a la eficadia (por evidentes motivos pedagógicos), aunque cumple perfectamente con su cometido:

#!/bin/bash

#Obtener usuarios con uidNumber >= 1000

grep "x:[1-9][0-9][0-9][0-9]:" /etc/passwd > tmp.txt

#Crear o reiniciar archivo ldif
>tmp.ldif

#Recorrer el archivo tmp.txt con la lista de usuarios
while read linea
do
   #Mostrar la línea que vamos a procesar
   echo "$linea"

   #Obtener datos 
   uid=$(echo $linea | cut -d: -f1) # El primer campo, separando con :
   nomComp=$(echo $linea | cut -d: -f5 | cut -d, -f1) # Lo que hay antes de la 1ª coma del 5º campo
   nomArray=($nomComp) #Convierte el nombre en un array de palabras
   nom=${nomArray[0]}
   if [ "$nom" == "" ]
   then
        nom=$uid
   fi
   ape=${nomArray[1]}
   if [ "$ape" == "" ]
   then
        ape=$uid
   fi
   inic=$(echo $nom | cut -c 1)$(echo $ape | cut -c 1)
   uidNum=$(echo $linea | cut -d: -f3)
   usrPass=$(grep $uid: /etc/shadow | cut -d: -f2)
   shell=$(echo $linea | cut -d: -f7)
   homedir=$(echo $linea | cut -d: -f6)

   #Volcar datos al archivo ldif
   echo "dn: uid=$uid,ou=usuarios,dc=somebooks,dc=local" >> tmp.ldif
   echo "objectClass: inetOrgPerson" >> tmp.ldif
   echo "objectClass: posixAccount" >> tmp.ldif
   echo "objectClass: shadowAccount" >> tmp.ldif
   echo "uid: $uid" >> tmp.ldif
   echo "sn: $ape" >> tmp.ldif
   echo "givenName: $nom" >> tmp.ldif
   echo "cn: $nomComp" >> tmp.ldif
   echo "displayName: $nomComp" >> tmp.ldif
   echo "uidNumber: $uidNum" >> tmp.ldif
   echo "gidNumber: 10000" >> tmp.ldif
   echo "userPassword: $usrPass" >> tmp.ldif
   echo "gecos: $nomComp" >> tmp.ldif
   echo "loginShell: $shell" >> tmp.ldif
   echo "homeDirectory: $homedir" >> tmp.ldif
   echo "shadowExpire: -1" >> tmp.ldif
   echo "shadowFlag: 0" >> tmp.ldif
   echo "shadowWarning: 7" >> tmp.ldif
   echo "shadowMin: 8" >> tmdddp.ldif
   echo "shadowMax: 999999" >> tmp.ldif
   echo "shadowLastChange: 10877" >> tmp.ldif
   echo "mail: ${nom[0]}.${nom[1]}@somebooks.com" >> tmp.ldif
   echo "postalCode: 29000" >> tmp.ldif
   echo "o: somebooks" >> tmp.ldif
   echo "initials: $inic" >> tmp.ldif
   echo >> tmp.ldif
done < tmp.txt

#Añadimos los nuevos usuarios a LDAP
ldapadd -x -D cn=admin,dc=somebooks,dc=local -W -f tmp.ldif
rm tmp.txt
rm tmp.ldif

Aunque no vamos a realizar una explicación pormenorizada del funcionamiento del script, a continuación se incluyen unas pautas con el fin de facilitar su interpretación:

  1. En la línea 5, comenzamos por buscar todas las líneas del archivo /etc/passwd que incluyan, a continuación del texto ‘x:‘, un número de 4 cifras. Estas líneas se copiarán a un archivo llamado tmp.txt.

  2. En la línea 8, creamos un archivo con el nombre tmp.ldif, que será el que contenga la definición de los usuarios para OpenLDAP. Hará la función del archivo usuario.ldif del apartado anterior. Si el archivo ya existe, perderá todo su contenido anterior. Si no, sencillamente se crea.

  3. Entre la línea 11 y la 63, hacemos un bucle que obtiene, en cada iteración, una línea del archivo tmp.txt, dentro de una variable llamada linea.

  4. Una vez obtenida una línea, la mostramos, en la línea 14, para que podamos comprobar que el usuario que se está procesando es el adecuado.

  5. Después, entre las líneas 17 y 34, vamos partiendo la información obtenida del archivo para obtener cada uno de sus campos por separado:

    1. En la línea 17, dividimos el texto en campos usando como separador el caracter de dos puntos (:) y nos quedamos con el primero de esos campos (cut -d: -f1). Eso es el nombre de la cuenta de usuario.

    2. En la línea 18 obtenemos el nombre completo del usuario. Primero el quinto campo, usando como separador los dos puntos (:) y, dentro de él, el primero usando como separador la coma (,).

    3. En la línea 19 convertimos el nombre completo en un array, de modo que podamos separar el nombre de los apellidos (líneas 20 y 25).

    4. En caso de que el nombre esté vacío, usamos el nombre de la cuenta (líneas 21 a 24). Y hacemos lo mismo con el apellido (líneas 26 a 29).

    5. En la línea 30, obtenemos la primera letra del nombre y del apellido para crear las iniciales.

    6. En la línea 32, buscamos la línea que contiene el nombre de la cuenta en el archivo /etc/shadow y nos quedamos con el segundo campo, que es la contraseña cifrada para ese usuario.

    7. Por último, en las líneas 31, 33 y 34 aplicamos el mismo procedimiento de la línea 17, para obtener el UID, la shell y el directorio home de la cuenta.

  6. A continuación, entre las líneas 37 y 62 componemos el contenido del archivo tmp.ldif para el usuario que nos ocupa.Cada línea se limita a realizar un echo con el formato adecuado para el archivo, usando los datos obtenidos en las líneas 17 a 34. La salida se añadirá (>>) al contenido del archivo tmp.ldif.

  7. Una vez terminado el recorrido del archivo tmp.txt, sólo quedará ejecutar el comando ldapadd que ya conocemos, y eliminar los archivos temporales que hemos creado durante el proceso (tmp.txt y tmp.ldif).

    Observa que, al añadir los usuarios al directorio OpenLDAP, no hemos mantenido su grupo original, sino que los hemos asignado al grupo usuarios que habíamos creado en el apartado anterior. De esta forma, podemos evitar la creación de un grupo distinto para cada usuario importado.

La ventaja que tiene usar el editor gEdit es que tiene la capacidad de colorear la sintaxis, lo que simplifica la escritura del código:

sudo gedit importar.sh

Abrimos el editor de textos, con privilegios de administración, indicándole el nombre del archivo que queremos crear.

Una vez escrito, o copiado, el código del script, ya podemos guardar su contenido.

Después, sólo quedará cerrar la ventana del editor.

A continuación, debemos otorgarle al script permisos de ejecución. Para lograrlo, deberemos asegurarnos de que nuestro directorio de trabajo es donde tenemos el archivo (recuerda que lo hemos llamado importar.sh y se encuentra en la carpeta personal del usuario con el que estamos trabajando). Una vez en ahí, sólo tenemos que ejecutar el siguiente comando:

sudo chmod +x importar.sh

Damos permisos de ejecución al script.

Como es lógico, el siguiente paso consistirá en ejecutar el script, aunque debemos recordar hacerlo con privilegios de administración:

sudo ./importar.sh

Como vemos en la imagen de abajo, lo primero que hace el script es mostrarnos la lista de los usuarios que van a ser importados (aunque, en este caso, sólo hay uno). Aunque tiene el formato del archivo /etc/passwd, en realidad lo que estamos viendo es el contenido del archivo ./tmp.txt.

Después, aunque no veamos nada, se habrá producido la creación del archivo ./tmp.ldif.

Por último, se ejecutará el comando ldapadd que, para completar su trabajo, necesitará que nos autentiquemos como administradores del directorio OpenLDAP. De ahí que se nos pida la contraseña.

Finalmente, la salida del comando ldapadd nos confirmará que la tarea se ha completado con éxito.

Como antes, podemos volver a usar el comando slapcat para mostrar el contenido completo del directorio, tal y como vimos más arriba.

Importar grupos locales al directorio OpenLDAP

La forma de importar los grupos locales es bastante parecida a la que hemos aplicado para importar los usuarios, por lo que, esta vez lo explicaremos de forma menos detallada.

Para comenzar, debemos saber que, de forma predeterminada, GNU/Linux, guarda la información sobre los grupos locales en el archivo /etc/group.

Como antes, el objetivo general del script será obtener estos datos y crear con ellos un nuevo archivo ldif. A continuación, volverá a ejecutar el comando ldapadd para añadirlos.

Para hacernos una idea del trabajo a realizar, debemos estudiar el aspecto general del archivo /etc/group, que será parecido al que muestra la siguiente imagen:

Contenido del archivo /etc/group.

Archivo /etc/group

Como hemos dicho, aquí seguiremos, aproximadamente, los pasos dados para crear el script anterior:

  • Copiaremos todas las líneas del archivo /etc/group que incluyan el texto ‘x:’, seguido de un número de 4 cifras, en un nuevo archivo llamado tmp.txt.

  • Crearemos un nuevo archivo llamado tmp.ldif donde después guardaremos la definición de los grupos para OpenLDAP.

  • Incluiremos un bucle que recorra el archivo tmp.txt línea a línea. La mostramos en pantalla y la descomponemos en sus diferentes elementos, volcándolos al archivo tmp.ldif.

  • Una vez terminado el recorrido del archivo tmp.txt, sólo quedará ejecutar el comando ldapadd, y eliminar los archivos temporales que hemos creado durante el proceso (tmp.txt y tmp.ldif).

Finalmente, el resultado deberá parecerse a este:

#!/bin/bash

#Obtener grupos con uidNumber >= 1000

grep "x:[1-9][0-9][0-9][0-9]:" /etc/group > tmp.txt

#Crear o reiniciar archivo ldif
>tmp.ldif

#Recorrer el archivo tmp.txt con la lista de grupos
while read linea
do
   #Mostrar la línea que vamos a procesar
   echo "$linea"

   #Obtener datos
   cn=$(echo $linea | cut -d: -f1) # El primer campo, separando con :
   gid=$(echo $linea | cut -d: -f3)
   usuarios=$(echo $linea | cut -d: -f4 | sed "s/,/ /g")

   #Volcar datos al archivo ldif
   echo "dn: cn=$cn,ou=grupos,dc=somebooks,dc=local" >> tmp.ldif
   echo "objectClass: posixGroup" >> tmp.ldif
   echo "cn: $cn" >> tmp.ldif
   echo "gidNumber: $gid" >> tmp.ldif
   echo "" >> tmp.ldif

   #añadir usuarios
   for usuario in ${usuarios} ; do
        echo "memberUid: ${usuario}" >> tmp.ldif
   done
done < tmp.txt

#Añadimos los nuevos grupos a LDAP
ldapadd -x -D cn=admin,dc=somebooks,dc=local -W -f tmp.ldif
rm tmp.txt
rm tmp.ldif

Como antes, volvemos a usar gEdit, que tiene la capacidad añadida de colorear la sintaxis, lo que simplifica la escritura del código:

sudo gedit importar-grupos.sh

Abrimos el editor de textos, con privilegios de administración, indicándole el nombre del archivo que queremos crear.

Una vez escrito, o copiado, el código del script, ya podemos guardar su contenido.

Después, sólo quedará cerrar la ventana del editor.

Igual que en el caso anterior, lo siguiente será otorgar al script permisos de ejecución. Volvemos a asegurarnos de que nuestro directorio de trabajo es el que contiene al archivo (recuerda que lo hemos llamado importar-grupos.sh y se encuentra en la carpeta personal del usuario con el que estamos trabajando).

Una vez en ahí, sólo tenemos que ejecutar el siguiente comando:

sudo chmod +x importar-grupos.sh

Damos permisos de ejecución al script.

Como vemos en la imagen de abajo, lo primero que hace el script es mostrarnos la lista de los grupos que van a ser importados (aunque, en este caso, vuelve a haber sólo uno). Aunque tiene el formato del archivo /etc/group, en realidad lo que estamos viendo es el contenido del archivo ./tmp.txt.

Después, aunque no veamos nada, se habrá producido la creación del archivo ./tmp.ldif.

Por último, se ejecutará el comando ldapadd que, para completar su trabajo, necesitará que nos autentiquemos como administradores del directorio OpenLDAP. De ahí que se nos pida la contraseña.

Como antes, la salida del comando ldapadd nos confirmará que la tarea se ha completado con éxito.

Recuerda que puedes volver a usar el comando slapcat para asegurarte de que el contenido completo del directorio es correcto.

Y esto es todo por el momento. Espero que esta serie de artículos te esté resultando útil.