Autenticación de clave SSH usando LDAP

59

En breve:

Me gustaría una forma de hacer la autenticación de clave SSH a través de LDAP.

Problema:

Utilizamos LDAP (slapd) para servicios de directorio y recientemente hemos pasado a usar nuestro propio AMI para crear instancias. La razón por la que el bit AMI es importante es que, idealmente , nos gustaría poder iniciar sesión con SSH a través de la autenticación de clave tan pronto como se ejecute la instancia y no tener que esperar a que nuestra herramienta de administración de configuración algo lenta inicie un script para agregar Las claves correctas para la instancia.

El escenario ideal es que, al agregar un usuario a LDAP, también agregamos su clave y podrán iniciar sesión de inmediato.

La autenticación de clave es imprescindible porque el inicio de sesión basado en contraseña es menos seguro y molesto.

He leído esta pregunta que sugiere que hay un parche para OpenSSH llamado OpenSSH-lpk para hacer esto, pero esto ya no es necesario con el servidor OpenSSH> = 6.2

Se agregó una opción de sshd_config (5) AuthorizedKeysCommand para admitir la obtención de claves autorizadas de un comando además de (o en lugar de) del sistema de archivos. El comando se ejecuta bajo una cuenta especificada por una opción AuthorizedKeysCommandUser sshd_config (5)

¿Cómo puedo configurar OpenSSH y LDAP para implementar esto?

c4urself
fuente

Respuestas:

64

Actualice LDAP para incluir el esquema OpenSSH-LPK

Primero necesitamos actualizar LDAP con un esquema para agregar el sshPublicKeyatributo a los usuarios:

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 )
    )

Cree una secuencia de comandos que consulte LDAP para la clave pública de un usuario:

El script debería generar las claves públicas para ese usuario, por ejemplo:

ldapsearch '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;s/sshPublicKey: //gp'

Actualice sshd_configpara apuntar a la secuencia de comandos del paso anterior

  • AuthorizedKeysCommand /path/to/script
  • AuthorizedKeysCommandUser nobody

Bonificación : Actualización sshd_configpara permitir la autenticación de contraseña de redes internas RFC1918 como se ve en esta pregunta:

Solo permita la autenticación de contraseña al servidor SSH desde la red interna

Enlaces útiles:

EDITAR: Usuario agregado nobodycomo TRS-80 sugerido

c4urself
fuente
66
Esto es fantástico, aunque sugeriría en AuthorizedKeysCommandUser nobodylugar de root.
TRS-80
Debe haber algo diferente en mi ldapsearch o sed porque canalizar la salida al comando de magia negra sed que tienes allí no me da salida, a pesar de que mi comando ldapsearch simple está devolviendo datos. Voy a tener que escribir un script para limpiar la salida en lugar de usar sed.
Chris L
1
Haga caso omiso de mi comentario anterior. Mi problema fue causado por tener una nueva línea final en la propiedad sshPublicKey, lo que a su vez hace que ldapsearch codifique en base64 todo. Simplifiqué el comando sed:ldapsearch -u -LLL -o ldif-wrap=no '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n 's/^[ \t]*sshPublicKey:[ \t]*\(.*\)/\1/p'
Chris L
1
@Chris de hecho menos magia negra, pero sed sigue siendo una función de hashing de una sola escritura y una sola dirección;)
Froyke
1
En mi versión de OpenSSH (5.3p1-122.el6) hay AuthorizedKeysCommandRunAsy noAuthorizedKeysCommandUser
mveroone
5

Para cualquiera que obtenga el error al ejecutar ldapsearch:

sed: 1: "/^ /{H;d};": extra characters at the end of d command

como estaba (en FreeBSD), la solución es cambiar el primer comando sed a:

/^ /{H;d;};

(agregando un punto y coma después de la 'd').

Scott
fuente
4

Solo quería compartir mi "método", mi lado del cliente es específico de Debian / Ubuntu, pero mi lado del servidor es básicamente el mismo que el anterior, pero con un poco más de "Cómo:"

Servidor:

Habilitar atributo de clave pública:

Crédito :

https://blog.shichao.io/2015/04/17/setup_openldap_server_with_openssh_lpk_on_ubuntu.html

cat << EOL >~/openssh-lpk.ldif
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 )
  )
EOL

Ahora use esto para agregar ldif:

ldapadd -Y EXTERNAL -H ldapi:/// -f ~/openssh-lpk.ldif

Agregar un usuario con clave pública SSH en phpLDAPadmin

Primero, cree un usuario con la plantilla "Genérico: Cuenta de usuario". Luego, vaya a la sección de atributos "objectClass", haga clic en "agregar valor" y elija el atributo "ldapPublicKey". Después de enviar, regrese a la página de edición del usuario, haga clic en "Agregar nuevo atributo" en la parte superior y elija "sshPublicKey", pegue la clave pública en el área de texto y finalmente haga clic en "Actualizar objeto".

El atributo sshPublicKey no se muestra - OpenLDAP PHPLDAP SSH Key Auth

Cliente Ubuntu:

apt-get -y install python-pip python-ldap
pip install ssh-ldap-pubkey
sh -c 'echo "AuthorizedKeysCommand /usr/local/bin/ssh-ldap-pubkey-wrapper\nAuthorizedKeysCommandUser nobody" >> /etc/ssh/sshd_config' && service ssh restart

Crear claves de prueba:

ssh-keygen -t rsa
FreeSoftwareServers
fuente
3

Esta no es una respuesta completa, solo una adición a la respuesta de c4urself . Hubiera agregado esto como un comentario, pero no tengo suficiente reputación para comentar, ¡así que por favor no desestime!

Este es el script que estoy usando para AuthorizedKeysCommand(basado en la versión de c4urself). Funciona independientemente de si el valor se devuelve en codificación base64 o no. Esto puede ser especialmente útil si desea almacenar varias claves autorizadas en LDAP: simplemente separe las claves con caracteres de nueva línea, de forma similar al archivo autorizado_claves.

#!/bin/bash
set -eou pipefail
IFS=$'\n\t'

result=$(ldapsearch '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey')
attrLine=$(echo "$result" | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;/sshPublicKey:/p')

if [[ "$attrLine" == sshPublicKey::* ]]; then
  echo "$attrLine" | sed 's/sshPublicKey:: //' | base64 -d
elif [[ "$attrLine" == sshPublicKey:* ]]; then
  echo "$attrLine" | sed 's/sshPublicKey: //'
else
  exit 1
fi
mbrgm
fuente