« Services/Kerberos+LDAP/Install » : différence entre les versions
| (4 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 497 : | Ligne 497 : | ||
Ajout de quelques ACL pour authoriser (et restreindre) le groupe kerberos aux comptes LDAP kadm et kdc, et ajout de quelques index au passage. | Ajout de quelques ACL pour authoriser (et restreindre) le groupe kerberos aux comptes LDAP kadm et kdc, et ajout de quelques index au passage. | ||
* La première règle ''olcAccess'' spécifie l'accès aux informations de mot de passe. Les utilisateurs anonymes auront un accès '''auth''' et tous les autres utilisateurs n'auront aucun accès. Ce type d'authentification peut sembler problématique, mais il n'est utilisé que par les connexions IPC (sockets UNIX). | |||
* La seconde règle ''olcAccess'' spécifie l'accès à la future branche '''ou=kerberos''' (qui contiendra la base de données Kerberos): le serveur d'administration Kerberos (kadmin) aura accès en écriture, le serveur Kerberos KDC aura accès en lecture. Et aucun accès pour les autres. | |||
* La troisième règle ''olcAccess'' permettra aux utilisateurs authentifiés de modifier leurs propres paramètres de ''shell'', l'attribut qui est inclus dans le schéma LDAP pour la classe d'objet ''posixAccount''. | |||
* La quatrième règle ''olcAccess'' permettra un accès en lecture à la base de l'arbre pour des choses comme ''supportedSASLMechanisms''. Cela permet aux clients de découvrir les mécanismes SASL que le serveur LDAP supporte. | |||
* La cinquième et dernière règle ''olcAccess'' spécifie l'ACL par défaut, c'est à dire qui détermine la politique d'accès par défaut à tout le reste dans l'arbre. Les utilisateurs authentifiés auront accès en lecture et les utilisateurs anonymes n'auront aucun accès. | |||
* Les autres règles ne sont que des ajouts d'index. | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF | ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF | ||
| Ligne 613 : | Ligne 619 : | ||
==== Modification du ldap pour qu'un ticket kerberos soit obligatoirement acquis pour se connecter au ldap ==== | ==== Modification du ldap pour qu'un ticket kerberos soit obligatoirement acquis pour se connecter au ldap ==== | ||
* Pour l'objet racine '''cn=config''', une directive de ''olcAuthzRegexp'' sera ajouté pour faire correspondre les comptes GSSAPI aux noms distinctifs (DN) du compte. | |||
* Un attribut ''olcSaslRealm'' sera ajouté pour préciser le royaume SASL, dans ce cas précis, un royaume Kerberos. | |||
* Pour la définition de base de données ''olcDatabase={2}hdb,cn=config'', le nom de l'utilisateur d'administration sera modifiée pour correspondre au DN auquel il sera traduit après la rencontre ''olcAuthzRegexp''. | |||
* Suppression du mot de passe pour l'utilisateur d'administration, de sorte qu'à partir de maintenant il ne sera possible d'utiliser ce compte qu'après obtention d'un ticket Kerberos. | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
ldapmodify -QY EXTERNAL -H ldapi:/// << EOF | ldapmodify -QY EXTERNAL -H ldapi:/// << EOF | ||
| Ligne 752 : | Ligne 763 : | ||
lastname= | lastname= | ||
email= | email= | ||
phone= | |||
title= | |||
function showhelp() | function showhelp() | ||
| Ligne 766 : | Ligne 779 : | ||
echo " -L <LASTNAME> User's lastname" | echo " -L <LASTNAME> User's lastname" | ||
echo " -e <EMAIL> Email account" | echo " -e <EMAIL> Email account" | ||
echo " -t <TITLE> Job title" | |||
echo " -p <PHONE NB> Phone number. Can be specified more than one time" | |||
} | } | ||
while getopts "?hl:u:g:f:L:e:" opt | while getopts "?hl:u:g:f:L:e:p:t:" opt | ||
do | do | ||
case "${opt}" in | case "${opt}" in | ||
| Ligne 792 : | Ligne 807 : | ||
e) | e) | ||
email=${OPTARG} | email=${OPTARG} | ||
;; | |||
t) | |||
title=${OPTARG} | |||
;; | |||
p) | |||
[ -z ${phone} ] && phone=${OPTARG} || phone="${phone} ${OPTARG}" | |||
;; | ;; | ||
*) | *) | ||
| Ligne 806 : | Ligne 827 : | ||
[ -z "${lastname}" ] && read -p "User's lastname: " lastname | [ -z "${lastname}" ] && read -p "User's lastname: " lastname | ||
[ -z "${email}" ] && read -p "Email account: " email | [ -z "${email}" ] && read -p "Email account: " email | ||
[ -z "${title}" ] && read -p "Job title: " title | |||
if [ -z "${phone}" ] | |||
then | |||
tmpphone= | |||
while true | |||
do | |||
read -p "Phone number: " tmpphone | |||
[ -z "${tmpphone}" ] && break || phone="${phone} ${tmpphone}" | |||
done | |||
fi | |||
[ -z "${login}" ] && echo "Missing login parameter" | [ -z "${login}" ] && echo "Missing login parameter" | ||
| Ligne 813 : | Ligne 844 : | ||
[ -z "${lastname}" ] && echo "Missing lastname parameter" | [ -z "${lastname}" ] && echo "Missing lastname parameter" | ||
[ -z "${email}" ] && echo "Missing email parameter" | [ -z "${email}" ] && echo "Missing email parameter" | ||
if [ -z "${login}" ] || [ -z "${uid}" ] || [ -z "${gid}" ] || [ -z "${firstname}" ] || [ -z "${lastname}" ] || [ -z "${email}" ] | if [ -z "${login}" ] || [ -z "${uid}" ] || [ -z "${gid}" ] || [ -z "${firstname}" ] || [ -z "${lastname}" ] || [ -z "${email}" ] || [ -z "${title}" ] | ||
then | then | ||
showhelp | showhelp | ||
| Ligne 819 : | Ligne 850 : | ||
fi | fi | ||
cat << EOF > /tmp/user.ldif | |||
dn: cn=${login},ou=groups,dc=didier,dc=com | dn: cn=${login},ou=groups,dc=didier,dc=com | ||
objectClass: top | objectClass: top | ||
| Ligne 828 : | Ligne 859 : | ||
dn: uid=${login},ou=people,dc=didier,dc=com | dn: uid=${login},ou=people,dc=didier,dc=com | ||
objectClass: top | objectClass: top | ||
objectClass: person | |||
objectClass: inetOrgPerson | |||
objectClass: organizationalPerson | objectClass: organizationalPerson | ||
objectClass: posixAccount | objectClass: posixAccount | ||
objectClass: shadowAccount | objectClass: shadowAccount | ||
| Ligne 841 : | Ligne 873 : | ||
userPassword: {CRYPT}* | userPassword: {CRYPT}* | ||
mail: ${email} | mail: ${email} | ||
displayName: ${firstname} ${lastname} | |||
title: ${title} | |||
EOF | EOF | ||
for nb in ${phone} | |||
do | |||
echo "telephoneNumber: ${nb}" >> /tmp/user.ldif | |||
done | |||
ldapadd -f /tmp/user.ldif | |||
rm -f /tmp/user.ldif | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| Ligne 857 : | Ligne 898 : | ||
$servers->setValue('server','host','127.0.0.1'); | $servers->setValue('server','host','127.0.0.1'); | ||
$servers->setValue('server','port',389); | $servers->setValue('server','port',389); | ||
$servers->setValue('server','base',array('ou=people,dc=didier,dc=com')); | $servers->setValue('server','base',array('ou=people,dc=didier,dc=com','ou=groups,dc=didier,dc=com')); | ||
$servers->setValue('login','auth_type','cookie'); | $servers->setValue('login','auth_type','cookie'); | ||
$servers->setValue('login','bind_id','uid=admin,ou=people,dc=didier,dc=com'); | $servers->setValue('login','bind_id','uid=admin,ou=people,dc=didier,dc=com'); | ||
| Ligne 865 : | Ligne 906 : | ||
Restriction d'accès grâce à Kerberos. Le détail se trouve dans le [[Services/Kerberos/Install#Authentification_Apache|tutorial d'installation de Kerberos, à la section "mise en place de l'authentification sur Apache"]] | Restriction d'accès grâce à Kerberos. Le détail se trouve dans le [[Services/Kerberos/Install#Authentification_Apache|tutorial d'installation de Kerberos, à la section "mise en place de l'authentification sur Apache"]] | ||
<syntaxhighlight lang="bash"> | |||
kadmin.local -q "addprinc -randkey http/kls.didier.com" | |||
kadmin.local -q "ktadd -k /etc/httpd/conf.d/http.keytab http/kls.didier.com" | |||
chown apache /etc/httpd/conf.d/http.keytab | |||
chmod 400 /etc/httpd/conf.d/http.keytab | |||
</syntaxhighlight> | |||
{{Admon/file|<path>/etc/httpd/conf.d/phpldapadmin.conf</path>| | |||
<syntaxhighlight lang="apache"> | <syntaxhighlight lang="apache"> | ||
Alias /phpldapadmin /usr/share/phpldapadmin/htdocs | Alias /phpldapadmin /usr/share/phpldapadmin/htdocs | ||
| Ligne 887 : | Ligne 935 : | ||
KrbMethodNegotiate Off | KrbMethodNegotiate Off | ||
</Directory> | </Directory> | ||
</syntaxhighlight> | </syntaxhighlight>}} | ||
== Références == | == Références == | ||
Dernière version du 27 mars 2015 à 11:39
Introduction
Ce document décrit comment configurer un serveur d'annuaire OpenLDAP et d'un maître MIT Kerberos KDC V sur le même hôte avec Kerberos utilisant LDAP comme base de données backend. Celui-ci combine l'excellente sécurité de cryptage offert par Kerberos avec le moteur de réplication supérieure d'OpenLDAP. C'est une stratégie rendue possible par le paquet <package>krb5-server-ldap</package> qui étend le schéma de base de données OpenLDAP pour soutenir Kerberos. Il fournit un plugin pour le serveur Kerberos pour lui permettre d'utiliser un annuaire LDAP comme base de données back-end.
Dans cet exemple, OpenLDAP est installé sur un hôte exécutant CentOS 7 . Le processus, suivi étape par étape, produira un serveur de fournisseur OpenLDAP avec une nouvelle Directory Information Tree (DIT), ainsi qu'un serveur maître Kerberos qui stocke sa base de données dans ce même DIT. Le système s'appuie fortement sur l'horodatage, donc la synchronisation du temps est primordiale sur tous les hôtes concernés.
Il sera d'abord nécessaire d'installer le système d'exploitation sur un nouvel hôte appelé kls.didier.com. Ce nom d'hôte doit pouvoir être résolu par le serveur DNS (direct et inverse). On pourra se référer au tutorial d'installation d'un serveur DNS.
Installation des pré-requis
Mise en place du nom d'hôte
hostnamectl set-hostname kls.didier.com
Installation des dépôts RPM
rpm -Uvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm \
http://koji.b2pweb.com/packages/b2pweb-release/1.4.0/1.el7.centos/noarch/b2pweb-release-1.4.0-1.el7.centos.noarch.rpm \
http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el7.rf.x86_64.rpm
Installation, démarrage/activation de chrony pour le maintien à l'heure
yum install chrony
systemctl start chronyd
systemctl enable chronyd
Modification de la configuration réseau afin d'utiliser notre serveur DNS
Cette modification est obligatoire car le serveur DNS va être différent de celui fournit par le DHCP.
IPV6INIT=yes
BOOTPROTO=dhcp
DEVICE=eth0
ONBOOT=yes
UUID=ef8c6371-688c-4080-b346-4e06de1ca34b
HWADDR=52:54:00:29:7A:BA
TYPE=Ethernet
DEFROUTE=yes
PEERDNS=no
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME="eth0"
DNS1="192.168.122.237"
qui produira automatiquement le fichier suivant
Installation d'outils de tests et de diagnostiques
- test: nslookup et dig
- diagnostique: netstat,nmap
yum install net-tools bind-utils nmap
serveur Kerberos en standalone
Cette partie est expliqué plus en détail dans le tutorial d'installation de Kerberos. Ici nous passerons rapidement sur l'installation.
Installation
yum install krb5-server krb5-workstation
Modification des fichiers de configuration
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = DIDIER.COM
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
DIDIER.COM = {
kdc = kls.didier.com
admin_server = kls.didier.com
}
[domain_realm]
.didier.com = DIDIER.COM
didier.com = DIDIER.COM
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
DIDIER.COM = {
#master_key_type = aes256-cts
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
}
Création de la base de données kerberos
La création de la base n'est utile que dans la version stanalone.
kdb5_util create -s
Ouverture des ports du firewall
firewall-cmd --permanent --add-service=kerberos
firewall-cmd --permanent --add-service=kadmin
firewall-cmd --permanent --add-service=kpasswd
firewall-cmd --permanent --add-port=749/tcp
firewall-cmd --reload
Démarrage/activation des services
systemctl start krb5kdc
systemctl start kadmin
systemctl enable kadmin
systemctl enable krb5kdc
Ajout de quelques principals de test
kadmin.local -q "addprinc srs/admin"
kadmin.local -q "addprinc didier"
kadmin.local -q "addprinc dev"
kadmin.local -q "addprinc watcher"
Export des principals (local)
Cet export n'est utile que dans la version standalone.
kadmin.local -q "ktadd -k /var/kerberos/krb5kdc/kadm5.keytab kadmin/admin"
kadmin.local -q "ktadd -k /var/kerberos/krb5kdc/kadm5.keytab kadmin/changepw"
L.D.A.P. en standalone
Installation
yum install openldap-servers openldap-clients krb5-server-ldap
Configuration
Cette partie est vraiment minimale car nous allons nous servir de LDAP pour stocker la configuration LDAP (cn=config).
OpenLDAP peut utiliser un des deux format de stockage pour les base de données Berkeley. Le format standard est appelé bdb. Une version plus récente a été optimisée pour les base de données hiérarchiques comme LDAP appelé hdb. CentOS/RHEL créé automatiquement une base au format hdb.
Les bases de données issues de bdb sont vraiment très optimisables et cette optimisation est faite dans le fichier appelé DB_CONFIG, fichier placé dans le même répertoire que les bases de données (typiquement <path>/var/lib/ldap</path>).
On va donc copier le fichier DB_CONFIG fournit par la distribution Linux.
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
Démarrage et activation du service LDAP
systemctl start slapd
systemctl enable slapd
Chargement des schémas standards
Un annuaire LDAP est une base de données au sens traditionnel du terme. Chaque donnée doit être définie dans un schéma décrivant les attributs de la donnée. Ce schéma doit être chargé dans la configuration de la base de données avant l'insertion de données.
Les schémas standards sont fournis comme fichier LDIF et peuvent être directement utilisés avec des commandes ldap.
Sur CentOS/RHEL, les fichiers LDIF sont disponibles depuis <path>/etc/openldap/schema</path>. Chacun est fourni dans deux formats: le schéma original LDAP et au format LDIF.
La plupart des annuaires LDAP utilisent 3 schémas de départ:
- core
- cosine
- inetorgperson
Ces 3 schémas définissent les objets et attributs nécessaire pour décrire une organisation: personne, groupes, bureau, etc...
On va aussi rajouté les schémas nis et kerberos pour notre usage.
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
Ajout du schema kerberos à ldap. Le fichier ne peut pas être inclus directement, car il provoque une erreur avec la cn=config.
On va devoir décomposer le mouvement
- Création d'un fichier temporaire qui inclus le schéma kerberos
echo 'include /usr/share/doc/krb5-server-ldap-1.11.3/kerberos.schema' > /tmp/schema_convert.conf
- Création d'un répertoire temporaire de travail
mkdir /tmp/krb5_ldif
- Création d'un fichier ldif
slaptest -f /tmp/schema_convert.conf -F /tmp/krb5_ldif
- Copie dans le répertoire des schémas ldap
cp /tmp/krb5_ldif/cn\=config/cn\=schema/cn\=\{0\}kerberos.ldif /etc/openldap/schema/kerberos.ldif
- Modification manuelle du fichier /etc/openldap/schema/kerberos.ldif
- Remplacer au début du fichier
dn: cn={0}kerberospardn: cn=kerberos,cn=schema,cn=config
- Remplacer au début du fichier
cn: {0}kerberosparcn: kerberos
- Supprimer les clés suivantes à la fin du fichier
structuralObjectClass: olcSchemaConfig
entryUUID: ...
creatorsName: cn=config
createTimestamp: ...
entryCSN: ...
modifiersName: cn=config
modifyTimestamp: ...
- Remplacer au début du fichier
- Import de notre fichier ldif correctement formaté
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/kerberos.ldif
- Suppression des fichiers/dossiers temporaires
rm -rf /tmp/schema_convert.conf /tmp/krb5_ldif
Modification du suffixe de l'annuaire
On lance une requête de changement de suffixe pour l'intégralité de l'annuaire. On le définit avec notre nom de domaine (ici: didier.com)
ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=didier,dc=com
EOF
modifying entry "olcDatabase={2}hdb,cn=config"
Mise en place de l'administrateur de l'annuaire
Une fois le suffixe de notre base de données défini, nous avons besoin de mettre à jour le DN de l' utilisateur qui sera en mesure d'apporter des modifications ( qui ne est pas l'utilisateur root du serveur ) .
Les noms d'utilisateur dans LDAP sont des noms distinctifs (Distinguished Names) d'objets stockés dans la base de données.
Mise en place du login administrateur
Nous pourrions garder le login (par défaut) "Manager" mais nous avons besoin de le placer dans la hiérarchie de notre base de données . Depuis que notre base de données est maintenant dc=didier,dc=com, l'administrateur doit être cn=administrateur,dc=didier,dc=com. Nous mettrons à jour de la même manière que nous l'avons fait pour le suffixe.
ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=admin,dc=didier,dc=com
EOF
modifying entry "olcDatabase={2}hdb,cn=config"
Ajout du mot de passe administrateur
OpenLDAP peut stocker les mots de passe en clair (mauvaise idée) ou utiliser plusieurs algorithmes de hashage. Le hashage par défaut est actuellement SHA1, qui est meilleur que les autres sans être toutefois sûr à 100%.
On commence par obtenir un hashage de notre mot de passe administrateur, en utilisant une commande LDAP. Celui-ci est donc directement utilisable dans les commandes ldap.
slappasswd
New password:
Re-enter new password:
{SSHA}hashstringgenerated
Puis on le met en place dans LDAP
ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}hashstringgenerated
EOF
modifying entry "olcDatabase={2}hdb,cn=config"
Ajout de l'enregistrement racine (organization)
La plupart des organisations utilisent leur nom de domaine en tant que modèle pour le nom distinctif racine (top DN) et LDAP utilisent un objet "organization". L'objet "organization" est un conteneur. Il est destiné à avoir des enfants de types arbitraires . Cela permet la création de toute structure pour la base de données. Parce que le suffixe est un nom de domaine, l'objet doit aussi être un composants d'organisation (Domain Component). Les Composants de domaine ne sont pas le plus haut niveau ou de conteneurs d'objets . Ils doivent avoir un parent. En combinant les classes de composants d'organisation et de domaine, nous créons un objet de niveau supérieur qui peut avoir le nom que nous voulons.
L'objet "organization" n'a qu'un seul attribut obligatoire: la valeur de o qui est une chaîne de caractère qui représente le nom de l'organisation. Il a aussi un attribut facultatif de description.
ldapadd -x -w ldappasswd -D cn=admin,dc=didier,dc=com -H ldapi:/// <<EOF
dn: dc=didier,dc=com
objectClass: dcObject
objectClass: organization
o: didier
dc: didier
EOF
adding new entry "dc=didier,dc=com"
Modification de la configuration générale du ldap (clients)
# # LDAP Defaults # # See ldap.conf(5) for details # This file should be world readable but not world writable. BASE dc=didier,dc=com URI ldap://kls.didier.com #SIZELIMIT 12 #TIMELIMIT 15 #DEREF never TLS_CACERTDIR /etc/openldap/cacerts # Turning this off breaks GSSAPI used with krb5 when rdns = false SASL_NOCANON on
LDAP over TLS
Mise en place de la PKI
Depuis le répertoire <path>/etc/openldap/certs/</path>
- Copie du bundle des hôtes de confiance
ln -s /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ca-bundle.crt
- Génération de la clé
openssl genrsa 4096 > server.key
- Génération du certificat (10 ans de validité)
openssl req -new -key server.key -x509 -days 3650 -out server.crt
Modification de la configuration LDAP
Ajout de la clé, du certificat et du bundle des hôtes de confiance à la configuration LDAP
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/ca-bundle.crt
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/server.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/server.key
EOF
Modification du fichier <path>/etc/sysconfig/slapd</path> afin de mettre le daemon à l'écoute de ldaps et de restreindre l'écoute non-sécurisée sur l'interface locale (IPv4 et IPv6).
SLAPD_URLS="ldapi:/// ldap:/// ldaps:///"
Ouverture du firewall
Seulement si le LDAP doit pouvoir être interrogé sur le canal non-sécurisé
firewall-cmd --permanent --add-service=ldap
Ouverture du canal sécurisé
firewall-cmd --permanent --add-service=ldaps
Et rechargement du parefeu
firewall-cmd --reload
Ldapisation de kerberos
Arrêt des services kerberos précédemment lancés. L'activation automatique au démarrage est toujours présente (et le restera)
systemctl stop krb5kdc
systemctl stop kadmin
Nettoyage de la base des principals, ainsi que de l'export local
On va ici déplacer les fichiers composants la base de données Kerberos, ainsi que l'export du principal administrateur. On peut aussi les supprimer purement et simplement.
mkdir /var/kerberos/krb5kdc.bak
mv /var/kerberos/krb5kdc/principal* /var/kerberos/krb5kdc.bak/
mv /var/kerberos/krb5kdc/kadm5.keytab /var/kerberos/krb5kdc.bak/
Modification de la conf kerberos
Ajout de paramètres relatifs à ldap.
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = DIDIER.COM
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
DIDIER.COM = {
kdc = kls.didier.com
admin_server = kls.didier.com
database_module = ldapconf
}
[domain_realm]
.didier.com = DIDIER.COM
didier.com = DIDIER.COM
[dbmodules]
ldapconf = {
db_library = kldap
ldap_kdc_dn = cn=kdc,ou=kerberos,dc=didier,dc=com
ldap_kadmind_dn = cn=kadm,ou=kerberos,dc=didier,dc=com
ldap_service_password_file = /var/kerberos/krb5kdc/krb5.stash
ldap_servers = ldapi:///
}
[dbdefaults]
ldap_kerberos_container_dn = ou=krb,dc=didier,dc=com
Ajout de l'utilisateur admin pour l'administration de Kerberos. L'asterisk représente le joker, c'est à dire toutes les commandes (y compris celle d'administration).
Une version détaillée des droits possibles est disponible dans le tutorial d'installation d'un serveur Kerberos.
Ajout du groupe (organization unit) et des utilisateurs kadm et kdc au LDAP
ldapadd -x -w ldappasswd -D cn=admin,dc=didier,dc=com -H ldapi:/// <<EOF
dn: ou=kerberos,dc=didier,dc=com
ou: krb
objectClass: organizationalUnit
EOF
slappasswd -s kdcpasswd
{SSHA}33YxNn3JD6etrXFTcI4z5W2qLeHDleV0
ldapadd -x -w ldappasswd -D cn=admin,dc=didier,dc=com -H ldapi:/// <<EOF
dn: cn=kdc,ou=kerberos,dc=didier,dc=com
cn: kdc
objectClass: simpleSecurityObject
objectClass: organizationalRole
description: Default bind DN for the Kerberos KDC server
userPassword: {SSHA}33YxNn3JD6etrXFTcI4z5W2qLeHDleV0
EOF
slappasswd -s kadmpasswd
{SSHA}nAI8HHoQUidezKFxQYt29VmQiKaqqYuX
ldapadd -x -w ldappasswd -D cn=admin,dc=didier,dc=com -H ldapi:/// <<EOF
dn: cn=kadm,ou=kerberos,dc=didier,dc=com
cn: kadm
objectClass: simpleSecurityObject
objectClass: organizationalRole
description: Default bind DN for the Kerberos Administration server
userPassword: {SSHA}nAI8HHoQUidezKFxQYt29VmQiKaqqYuX
EOF
Création de la base kerberos et export des comptes ldap
Export des comptes
- kadm: cn=kadm,ou=kerberos,dc=didier,dc=com
- kdc: cn=kdc,ou=kerberos,dc=didier,dc=com
kdb5_ldap_util -D cn=admin,dc=didier,dc=com -H ldap://kls.didier.com create -subtrees ou=kerberos,dc=didier,dc=com -r DIDIER.COM -s
kdb5_ldap_util -D cn=admin,dc=didier,dc=com stashsrvpw -f /var/kerberos/krb5kdc/krb5.stash cn=kdc,ou=kerberos,dc=didier,dc=com
kdb5_ldap_util -D cn=admin,dc=didier,dc=com stashsrvpw -f /var/kerberos/krb5kdc/krb5.stash cn=kadm,ou=kerberos,dc=didier,dc=com
Modification des ACL LDAP
Ajout de quelques ACL pour authoriser (et restreindre) le groupe kerberos aux comptes LDAP kadm et kdc, et ajout de quelques index au passage.
- La première règle olcAccess spécifie l'accès aux informations de mot de passe. Les utilisateurs anonymes auront un accès auth et tous les autres utilisateurs n'auront aucun accès. Ce type d'authentification peut sembler problématique, mais il n'est utilisé que par les connexions IPC (sockets UNIX).
- La seconde règle olcAccess spécifie l'accès à la future branche ou=kerberos (qui contiendra la base de données Kerberos): le serveur d'administration Kerberos (kadmin) aura accès en écriture, le serveur Kerberos KDC aura accès en lecture. Et aucun accès pour les autres.
- La troisième règle olcAccess permettra aux utilisateurs authentifiés de modifier leurs propres paramètres de shell, l'attribut qui est inclus dans le schéma LDAP pour la classe d'objet posixAccount.
- La quatrième règle olcAccess permettra un accès en lecture à la base de l'arbre pour des choses comme supportedSASLMechanisms. Cela permet aux clients de découvrir les mécanismes SASL que le serveur LDAP supporte.
- La cinquième et dernière règle olcAccess spécifie l'ACL par défaut, c'est à dire qui détermine la politique d'accès par défaut à tout le reste dans l'arbre. Les utilisateurs authentifiés auront accès en lecture et les utilisateurs anonymes n'auront aucun accès.
- Les autres règles ne sont que des ajouts d'index.
ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: to attrs=userPassword,shadowLastChange
by anonymous auth
by * none
-
add: olcAccess
olcAccess: to dn.subtree="ou=kerberos,dc=didier,dc=com"
by dn.exact="cn=kadm,ou=kerberos,dc=didier,dc=com" write
by dn.exact="cn=kdc,ou=kerberos,dc=didier,dc=com" read
by * none
-
add: olcAccess
olcAccess: to attrs=loginShell
by self write
by users read
by * none
-
add: olcAccess
olcAccess: to dn.base=""
by * read
-
add: olcAccess
olcAccess: to *
by users read
by * none
-
add: olcDbIndex
olcDbIndex: uid eq
-
add: olcDbIndex
olcDbIndex: dc eq
-
add: olcDbIndex
olcDbIndex: uidNumber eq
-
add: olcDbIndex
olcDbIndex: gidNumber eq
-
add: olcDbIndex
olcDbIndex: memberUid eq
-
add: olcDbIndex
olcDbIndex: uniqueMember eq
-
add: olcDbIndex
olcDbIndex: krbPrincipalName eq,pres,sub
-
add: olcDbIndex
olcDbIndex: krbPwdPolicyReference eq
EOF
Le service kerberos n'est pas encore démarré.
kadmin.local -q "ank admin"
kadmin.local -q "ank didier"
kadmin.local -q "ank srs/admin"
Démarrage des services kerberos
systemctl start krb5kdc
systemctl start kadmin
Kerberization de L.D.A.P.
Mise en place
Installation de Cyrus GSSAPI
yum install cyrus-sasl-gssapi
Création et export d'un principal LDAP
Le principal ldap/kls.didier.com devra être lisible par l'utilisateur ldap et à l'emplacement par défaut (/etc/krb5.keytab) sinon cyrus ne pourra le trouver.
rm -f /etc/krb5.keytab
kadmin.local -q "addprinc -randkey ldap/kls.didier.com"
kadmin.local -q "ktadd -k /etc/krb5.keytab ldap/kls.didier.com@DIDIER.COM"
klist -ke /etc/krb5.keytab
chown root:ldap /etc/krb5.keytab
chmod 440 /etc/krb5.keytab
Mise en place de notre keytab pour le daemon LDAP
Spécification de notre keytab pour slapd dans le fichier <path>/etc/sysconfig/slapd</path>
KRB5_KTNAME="FILE:/etc/krb5.keytab"
Ajout des groupes ldap (organizational unit) people et groups
ldapadd -xWD cn=admin,dc=didier,dc=com <<EOF
dn: ou=people,dc=didier,dc=com
objectClass: organizationalUnit
ou: people
dn: ou=groups,dc=didier,dc=com
objectClass: organizationalUnit
ou: groups
EOF
Modification du ldap pour qu'un ticket kerberos soit obligatoirement acquis pour se connecter au ldap
- Pour l'objet racine cn=config, une directive de olcAuthzRegexp sera ajouté pour faire correspondre les comptes GSSAPI aux noms distinctifs (DN) du compte.
- Un attribut olcSaslRealm sera ajouté pour préciser le royaume SASL, dans ce cas précis, un royaume Kerberos.
- Pour la définition de base de données olcDatabase={2}hdb,cn=config, le nom de l'utilisateur d'administration sera modifiée pour correspondre au DN auquel il sera traduit après la rencontre olcAuthzRegexp.
- Suppression du mot de passe pour l'utilisateur d'administration, de sorte qu'à partir de maintenant il ne sera possible d'utiliser ce compte qu'après obtention d'un ticket Kerberos.
ldapmodify -QY EXTERNAL -H ldapi:/// << EOF
dn: cn=config
changetype: modify
add: olcAuthzRegexp
olcAuthzRegexp: uid=([^,]+),cn=didier.com,cn=gss-spnego,cn=auth
uid=$1,ou=people,dc=didier,dc=com
-
add: olcSaslRealm
olcSaslRealm: DIDIER.COM
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: uid=admin,ou=people,dc=didier,dc=com
-
delete: olcRootPW
EOF
Redémarrage du service slapd
systemctl restart slapd
Tests
Avant d'obtenir un ticket kerberos
L'échec est ici prévisible et même souhaité pour tous les tests sans ticket kerberos
ldapsearch -xLLL ou=people
No such object (32)
ldapsearch -xWLLL -D cn=admin,dc=didier,dc=com ou=people
Enter LDAP Password:
ldap_bind: Invalid credentials (49)
ldapsearch -xWLLL -D uid=admin,ou=people,dc=didier,dc=com ou=people
Enter LDAP Password:
ldap_bind: Invalid credentials (49)
ldapsearch -LLL ou=people
SASL/GSS-SPNEGO authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure.
Minor code may provide more information (SPNEGO cannot find mechanisms to negotiate)
Obtention du ticket kerberos et vérification de l'acquisition
kinit admin
klist
Ticket cache: KEYRING:persistent:0:0
Default principal: admin@DIDIER.COM
Valid starting Expires Service principal
20/03/2015 16:05:38 21/03/2015 16:05:38 krbtgt/DIDIER.COM@DIDIER.COM
renew until 20/03/2015 16:05:38
Relance du test avec ticket kerberos pour admin
Le même test fonctionne maintenant
ldapsearch -LLL ou=people
SASL/GSS-SPNEGO authentication started
SASL username: admin@DIDIER.COM
SASL SSF: 56
SASL data security layer installed.
dn: ou=people,dc=didier,dc=com
objectClass: organizationalUnit
ou: people
ldapwhoami
SASL/GSS-SPNEGO authentication started
SASL username: admin@DIDIER.COM
SASL SSF: 56
SASL data security layer installed.
dn:uid=admin,cn=didier.com,cn=gss-spnego,cn=auth
Test depuis un client externe
Le même type de fonctionnent est observé sur les clients pour l'interrogation du LDAP (lecture seule). Le principal kerberos doit exister et un ticket doit être acquis avant l'interrogation.
ldapsearch -LLL "(objectclass=inetOrgPerson)" mail
SASL/GSS-SPNEGO authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure.
Minor code may provide more information (SPNEGO cannot find mechanisms to negotiate)
kinit didier
ldapsearch -LLL "(objectclass=inetOrgPerson)" mail
SASL/GSS-SPNEGO authentication started
SASL username: didier@DIDIER.COM
SASL SSF: 56
SASL data security layer installed.
dn: uid=didier,ou=people,dc=didier,dc=com
mail: dfabert@didier.com
dn: uid=bastien,ou=people,dc=didier,dc=com
mail: bhermitte@didier.com
dn: uid=gilles,ou=people,dc=didier,dc=com
mail: ggaudin@didier.com
Outils complémentaires
Script d'ajout d'utilisateur au LDAP
#!/bin/bash
login=
uid=
gid=
firstname=
lastname=
email=
phone=
title=
function showhelp()
{
echo "Add a new user to LDAP"
echo
echo "Usage $(basename $0)"
echo
echo "Options:"
echo " -l <LOGIN> User login"
echo " -u <UID> User system identifiant"
echo " -g <GID> Group system identifiant"
echo " -f <FIRSTNAME> User's firstname"
echo " -L <LASTNAME> User's lastname"
echo " -e <EMAIL> Email account"
echo " -t <TITLE> Job title"
echo " -p <PHONE NB> Phone number. Can be specified more than one time"
}
while getopts "?hl:u:g:f:L:e:p:t:" opt
do
case "${opt}" in
h|\?)
showhelp
exit 0
;;
l)
login=${OPTARG}
;;
u)
uid=${OPTARG}
;;
g)
gid=${OPTARG}
;;
f)
firstname=${OPTARG}
;;
L)
lastname=${OPTARG}
;;
e)
email=${OPTARG}
;;
t)
title=${OPTARG}
;;
p)
[ -z ${phone} ] && phone=${OPTARG} || phone="${phone} ${OPTARG}"
;;
*)
showhelp
exit 1
;;
esac
done
[ -z "${login}" ] && read -p "User login: " login
[ -z "${uid}" ] && read -p "User system identifiant (uid): " uid
[ -z "${gid}" ] && read -p "Group system identifiant (gid): " gid
[ -z "${firstname}" ] && read -p "User's firstname: " firstname
[ -z "${lastname}" ] && read -p "User's lastname: " lastname
[ -z "${email}" ] && read -p "Email account: " email
[ -z "${title}" ] && read -p "Job title: " title
if [ -z "${phone}" ]
then
tmpphone=
while true
do
read -p "Phone number: " tmpphone
[ -z "${tmpphone}" ] && break || phone="${phone} ${tmpphone}"
done
fi
[ -z "${login}" ] && echo "Missing login parameter"
[ -z "${uid}" ] && echo "Missing uid parameter"
[ -z "${gid}" ] && echo "Missing gid parameter"
[ -z "${firstname}" ] && echo "Missing firstname parameter"
[ -z "${lastname}" ] && echo "Missing lastname parameter"
[ -z "${email}" ] && echo "Missing email parameter"
if [ -z "${login}" ] || [ -z "${uid}" ] || [ -z "${gid}" ] || [ -z "${firstname}" ] || [ -z "${lastname}" ] || [ -z "${email}" ] || [ -z "${title}" ]
then
showhelp
exit 1
fi
cat << EOF > /tmp/user.ldif
dn: cn=${login},ou=groups,dc=didier,dc=com
objectClass: top
objectClass: posixGroup
cn: ${login}
gidNumber: ${gid}
dn: uid=${login},ou=people,dc=didier,dc=com
objectClass: top
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${login}
uidNumber: ${uid}
gidNumber: ${gid}
cn: ${firstname}
sn: ${lastname}
loginShell: /bin/bash
homeDirectory: /home/${login}
userPassword: {CRYPT}*
mail: ${email}
displayName: ${firstname} ${lastname}
title: ${title}
EOF
for nb in ${phone}
do
echo "telephoneNumber: ${nb}" >> /tmp/user.ldif
done
ldapadd -f /tmp/user.ldif
rm -f /tmp/user.ldif
phpldapadmin
Installation de l'application web
yum install httpd mod_ssl mod_auth_kerb phpldapadmin
Configuration dans le fichier <path>/etc/phpldapadmin/config.php</path>
$servers->newServer('ldap_pla');
$servers->setValue('server','name','LDAP Server');
$servers->setValue('server','host','127.0.0.1');
$servers->setValue('server','port',389);
$servers->setValue('server','base',array('ou=people,dc=didier,dc=com','ou=groups,dc=didier,dc=com'));
$servers->setValue('login','auth_type','cookie');
$servers->setValue('login','bind_id','uid=admin,ou=people,dc=didier,dc=com');
$servers->setValue('login','bind_pass','ldappasswd');
$servers->setValue('server','tls',false);
Restriction d'accès grâce à Kerberos. Le détail se trouve dans le tutorial d'installation de Kerberos, à la section "mise en place de l'authentification sur Apache"
kadmin.local -q "addprinc -randkey http/kls.didier.com"
kadmin.local -q "ktadd -k /etc/httpd/conf.d/http.keytab http/kls.didier.com"
chown apache /etc/httpd/conf.d/http.keytab
chmod 400 /etc/httpd/conf.d/http.keytab
Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs
<Directory /usr/share/phpldapadmin/htdocs>
<RequireAll>
<RequireAny>
Require local
Require ip 192.168.122.1
</RequireAny>
Require user admin@DIDIER.COM
</RequireAll>
SSLRequireSSL
AuthType Kerberos
AuthName "LDAP Admin"
KrbAuthRealms DIDIER.COM
KrbServiceName http/kls.didier.com
Krb5KeyTab /etc/httpd/conf.d/http.keytab
KrbSaveCredentials off
KrbVerifyKDC off
KrbMethodNegotiate Off
</Directory>
Références
- Installation et initialisation de ldap sur centos 7: http://injustfiveminutes.com/2014/10/28/how-to-initialize-openldap-2-4-x-server-with-olc-on-centos-7/
- Tuturial pour Debian de kerberos+ldap: http://www.rjsystems.nl/en/2100-d6-kerberos-openldap-provider.php