Escenario - Poblar un directorio LDAP desde un fichero CSV
Introducción
En nuestro escenario vamos a realizar la instalación y configuración de OpenLDAP en la máquina Alfa
. Lo haremos utilizando como base el nombre DNS asignado a la máquina, alfa.mariajesus.gonzalonazareno.org
.
En esta ocasión, vamos a crear entre todos los alumnos de la clase, los que vayamos a hacer dicha práctica, un fichero CSV que incluya la siguiente información:
- Nombre del alumno
- Apellidos del alumno
- Dirección de correo electrónico
- Nombre del equipo
- Dirección IP del equipo
- Clave pública SSH del equipo
El mío quedaría así:
Maria Jesus,Alloza,Rodriguez,mariajesus.allozarodriguez@gmail.com,maria,ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDofL1X9E8awIaBBO3RO4fsgi1MgqRSSbx8eJIVjdEJMgIA0ZMlYGppxUADGCdKTZdTLOZwPkwnD53ydWKU+zmu806hGHpdKQD8UkmCvRTO1tNcDdWYeGU9kNbsuxezzdMBpumjx6XQ/IobvXSfG6NVFQmU1GbtVtAHPNKRSO5ql0irL/dUOK/aoNvat0HD182ShRUWCrkzio7iNXD2yFuNyu3KCcdi06bcUQOXj3nfTlzBRPcEawXxOCOaKMm5Za/huGfM9DNrS58vB+j+0Q5qLDPMWV72c9tXHhHw+/ESU8EKh3v7jpBdDt7i6PpEy9Y4p1RUEOfBkJ9pcstLsz6od5AFcs0fqptBuDR1kPwMlT4wSSqSo7K7F19PlywjUTPNEPlzjc2/meNDGBJNMQXjx5FJjivtkPueL5fR/yN0ubGgOQmDRZ2tkl8LZ5UPXSHbxJ6e4RjPYXzMX9Nc7vFbdkZbMudRy40fvxqL+OSnvZ1Y/3OQqf7NQdoNJdfLHrM= maria@delta.mariajesus.gonzalonazareno.org
Ivan,Pina Castillo,ivanpicas88@gmail.com,ivan,ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCfYm123AV12rRYM+tPkrd0Hrzc9Py32Ov8JVZCnH5zVBj3I/IxE08LUhccSSx9aD0DrW+RdfpmLCSBTgGnbdM9eYlq3jxoBqqye4DQeXLSPyXcp/qRPGPsNO+eGypVhRB+Oq9B+ktrHgzAXQSP1yjmjN57H7GVBnMEJhpCEVXk5vWgMhVNxsDSF6lHrbiaYLtunTtt+fNgrprzXuUqhUwEDRt6/ktwad420J7kmqkB4dQuex3hV+16l1GyNH8AJzNzoinTiLr/jW8Ja0udgIknsxFvZ5Df+ACCrXfIFwvdPTm6Nya0jCm9vFx5yc5O1E07qlbAAn3FiIfS5Udjs6rNZjfFH5GmlpodhcGy4nkCYZvylnEayIa/ak4wA7oDft60hlHBMCHMoyY3ZcIkWGmVkwnTB3xfxfykPeD14zQAlIuMol9RNmPUbDYtbfY64npLPmagUIHSpwwbs1byEBbzzqzG8qcCAPUk3mK6oB5+OKUNJDv+4MM+suj+Y/PnWM8= debian@delta
Juan Jesus,Alejo Sillero,juanjesusalejosillero@gmail.com,juanje,ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDzLgcT2qKvflOcKWjUGX0ecoVWN+phHx7dEws3b/rY/xAichGJ6oP8ucD4lVJ8XVrEOaUgqQ1laPK33+u9MmzARx4g17/jKcwepUWdkKVA2++RWG3bsNgxCCkR1Gi7XMAAjwq8/17OjCj+4bvfTPlW5FSjDqaLhfqqeDtKpFJ3wjGG5sjNPC0GU4cRKzggZaR40ld7siaOiMteQ8X6bIggeXw+ULGiUhB4/uoLu0z69AzGgDfoPJuJEx4pPlcnOip/TAuL/pUjTjdUUDTsrZSJegWoLmRwylKvwtX8WojqI2TnTOyLT0IG1oStq4gC4AKOiCqfiBOm25bFfX0lW0uUaR1RjEuGz3jV0vkH3pCiuarNk5KnEQQqUO0x6ZvdCvOlsWYoiDQ6MclGKfUkUzC1uST5khs4xB1zQAZ5795on4SV8STASTwjpxuTuk7v4lTxrm8bTAF4bWiezgOQ0aFr7P0APygX0rbCR1aXoGfSyrrvqOUtkUzpiWwZwOpj0K0= juanjesus@delta.juanjesus.gonzalonazareno.org
Alejandro,Montes Delgado,aaleemd11@gmail.com,alemd,ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCvd5Lg3K1k1WeHYHE3T5aPSEx/duCM87J2LFhgFODU3Z0+1mE5bjDUzvrUTVoHdMu1phOd8IS2vPCL2Ei8PjooLdLrsqHtFN9JYvtBRRhTs5tV3JSGaaFrljYtiITbulVTHBTqssrr4VfJ1jxMF9aSVcPjfVxsNMo01AhK8PAnCiSVBru9BUYgoG+7rCVMeB78qTXyuKNLoFqsuIPmQeV8D0JGKGozS2cikflyEOgYC+UwILUliV0dVtlpPltOOMLKngWF1fyjnfsJykiULI+l20Iid5QtDx5SK6nLRTtrr9MYCZbSJqAKVsxxKIYY5I+qSNsikgNrTnWJVq6z4zr5u4AqazjiDqX+266cDBf7rEq9GA9OZuul4/Kzy+PB9+w5rCgneSP7iL38ehQSjWzfpD1ny8mxCFmwuEwFBpGYhYHNywBYg8f1iMayjBeatFIU8WUCrCct0y1Zlf/Hn+Lzd5xb4aJgWd+mMyMmhZPcTAC6UN03tM2b0s6wjP8DzJc= ubuntu@delta
Esquema openssh-lpk
Tras haber creado los ficheros, vamos a añadir el esquema openssh-lpk al servidor LDAP. Para ello, vamos a crear un fichero llamado openssh-lpk.ldif:
vi /etc/ldap/schema/openssh-lpk.ldif
Y añadimos el siguiente contenido:
dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
DESC 'MANDATORY: OpenSSH Public key'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
DESC 'MANDATORY: OpenSSH LPK objectclass'
MAY ( sshPublicKey $ uid )
)
Lo siguiente será añadir el esquema al directorio que utilizamos para el servidor LDAP ejecutando el siguiente comando en nuestra terminal en la máquina alfa
:
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/openssh-lpk.ldif
Script en Python 🐍
Para realizar el script, primero deberemos crear un entorno virtual. Para ello, ejecutamos el siguiente comando:
python3 -m venv ldap
El fin del entorno virtual es instalar el módulo python-ldap
que nos permitirá conectarnos al servidor LDAP. Para ello, activamos el entorno virtual y ejecutamos el siguiente comando:
source ldap/bin/activate
pip install python3-ldap
pip install ldap3==2.6
Una vez instalado el módulo, vamos a crear el script. Para ello, creamos un fichero llamado ldap.py
:
vi ldap.py
Y añadimos el siguiente contenido:
#!/usr/bin/env python
import ldap3
from ldap3 import Connection, ALL
from getpass import getpass
from sys import exit
### VARIABLES
# Shell que se le asigna a los usuarios
shell = '/bin/bash'
# Ruta absoluta del directorio que contiene los directorios personales de los usuarios. Terminado en "/"
home_dir = '/home/ldap'
# El valor inicial para los UID que se asignan al insertar usuarios.
uid_number = 5000
# El GID que se le asigna a los usuarios. Si no se manda al anadir el usuario da error.
gid = 5000
### VARIABLES
# Leemos el fichero .csv de los usuarios y guardamos cada linea en una lista.
with open('usuarios.csv', 'r') as usuarios:
usuarios = usuarios.readlines()
### Parametros para la conexion
ldap_ip = 'ldap://alfa.mariajesus.gonzalonazareno.org:636'
dominio_base = 'dc=mariajesus,dc=gonzalonazareno,dc=org'
user_admin = 'admin'
contrasena = getpass('Contrasena: ')
# Intenta realizar la conexion.
conn = Connection(ldap_ip, 'cn={},{}'.format(user_admin, dominio_base),contrasena)
# conn.bind() devuelve "True" si se ha establecido la conexion y "False" en caso contrario.
# Si no se establece la conexion imprime por pantalla un error de conexion.
if not conn.bind():
print('No se ha podido conectar con ldap')
if conn.result['description'] == 'invalidCredentials':
print('Credenciales no validas.')
# Termina el script.
exit(0)
# Recorre la lista de usuarios
for user in usuarios:
# Separa los valores del usuario usando como delimitador ",", y asigna cada valor a la variable correspondiente.
user = user.split(',')
cn = user[0]
sn = user[1]
mail = user[2]
uid = user[3]
ssh = user[4]
#Anade el usuario.
conn.add(
'uid={},ou=Personas,{}'.format(uid, dominio_base),
object_class =
[
'inetOrgPerson',
'posixAccount',
'ldapPublicKey'
],
attributes =
{
'cn': cn,
'sn': sn,
'mail': mail,
'uid': uid,
'uidNumber': str(uid_number),
'gidNumber': str(gid),
'homeDirectory': '{}{}'.format(home_dir,uid),
'loginShell': shell,
'sshPublicKey': str(ssh)
})
if conn.result['description'] == 'entryAlreadyExists':
print('El usuario {} ya existe.'.format(uid))
# Aumenta el contador para asignar un UID diferente a cada usuario (cada vez que ejecutemos el script debemos asegurarnos de ante mano que no existe dicho uid en el directorio ldap, o se solaparian los datos)
uid_number += 1
#Cierra la conexion.
conn.unbind()
Lo siguiente serña comprobar que el script funciona correctamente. Para ello, ejecutamos el siguiente comando:
python3 ldap.py
Comprobamos que se han añadido los usuarios correctamente en el directorio LDAP:
ldapsearch -x -LLL -b dc=mariajesus,dc=gonzalonazareno,dc=org -D "cn=admin,dc=mariajesus,dc=gonzalonazareno,dc=org" -W
Configuramos el sistema para que los usuarios sean autenticados por LDAP
Para que los usuarios sean autenticados por LDAP, debemos modificar el archivo /etc/ldap/ldap.conf
y añadir las siguientes líneas:
BASE dc=mariajesus,dc=gonzalonazareno,dc=org
URI ldap://alfa.mariajesus.gonzalonazareno.org
También deberemos modificar el archivo /etc/nsswitch.conf
y añadir la siguiente línea:
passwd: files systemd ldap
group: files systemd ldap
shadow: files ldap
Instalamos el paquete libpam-ldap
:
apt install libpam-ldap
Y lo configuramos:
- LDAP server URI: `ldap://127.0.0.1
- Distinguished name of search base:
dc=mariajesus,dc=gonzalonazareno,dc=org
- LDAP version:
3
- LDAP acount for root DN:
cn=admin,dc=mariajesus,dc=gonzalonazareno,dc=org
Configuramos el sistema para que los usuarios puedan acceder por SSH
Ante todo, vamos aconfigurarlo para que dichos usuarios tengan su propia /home
:
echo "session requiered pam_mkhomedir.so" >> /etc/pam.d/common-session
Ahora, le toca el turno a la configuración del sistema, para que los usuarios puedan acceder por SSH. Para ello, crearemos un script que se encargará de buscar las claves. Lo añadiremos aldirectorio /opt
para que tenga los permisos necesarios, estando en un dorectorio perteneciente a root
:
vi /opt/search.sh
#!/bin/bash
# Busca la clave publica del usuario en el directorio LDAP.
ldapsearch -x -u -LLL -o ldif-wrap=no '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n 's/^[ \t]*sshPublicKey::[ \t]*\(.*\)/\1/p' | base64 -d
Este comando es bastante complejo, así que vamos a explicarlo:
ldapsearch
: comando para buscar en el directorio LDAP.-x
: autenticación simple.-u
: no mostrar el prompt.-LLL
: no mostrar los mensajes de error.-o ldif-wrap=no
: no mostrar los mensajes de error.(&(objectClass=posixAccount)(uid='"$1"'))'
: busca el usuario que se le pasa como parámetro.sshPublicKey'
: busca la clave pública del usuario.sed -n 's/^[ \t]*sshPublicKey::[ \t]*\(.*\)/\1/p'
: elimina la parte de la clave pública que no nos interesa.base64 -d
: decodifica la clave pública.
Una vez creado, le damos permisos de ejecución:
chmod 755 /opt/search.sh
Para hacer una prueba, ejecutamos el script:
source /opt/search.sh maria
Tras esta comprobación, nos dirigimos al fichero /etc/ssh/sshd_config
y añadimos las siguientes líneas:
AuthorizedKeysCommand /opt/search.sh
AuthorizedKeysCommandUser nobody
Reiniciamos el servicio SSH:
systemctl restart sshd
Y comprabamos que funciona correctamente:
ssh maria@alfa
Para comprobar el funcionamiento completo, he añadido una nueva clave, la de mi compañero Antonio. He comprobado que se ha añadido correctamente en el directorio LDAP, pero al realizar la conexion, no le esposible dado que le pide una contraseña.