central usermanagement

...using ldap and kerberos

motivation

warum:

  • skaliert
  • sicherheit
  • komfort (single sign on) warum nicht:

  • fehlerquelle komplexitaet

  • gefahr single point of failure / break in -> infrastruktur!

theorie

recommended reading:

  • http://www.openinput.com/auth-howto/index.html
  • http://www.pdc.kth.se/heimdal/
  • http://www.openldap.org/doc/admin23/ architektur:

  • trusted third party, der KDC. hat gemeinsames secret mit allen hosts/services/usern. "principals". generiert auf anfrage ticket mit zeit, ip, und welcher user zu welchem service. design decisions:

  • keine passwoerter im ldap, alles via kerberos, rueckwaertskompatibilitaet via pam_krb, nicht sasl oder pam_ldap.

  • kerberos datenbank im ldap, keine seperate replikation noetig (nur mit heimdal).
  • eigene ldap range fuer uid/groupid, root und systemuser bleiben lokal falls das netzwerk spinnt.

required software

zutaten am server:

  • heimdal kerberos (ldap), alternativen: mit, shishi
  • openldap, alternativ: mysql, postgresql
  • wohlgepflegtes dns und reverse-dns
  • schwer empfohlen: replikation und redundanz
sudo aptitude install slapd heimdal-kdc

zutaten am host:

  • libnss-ldap
  • pam-krb5
  • sasl mit gssapi provider
  • richtige zeit, zb. openntpd (kann aber nicht stratum faken fuer windows)
  • kerberized client/serversoftware (zb. openssh, apache2)
sudo aptitude install libnss-ldap libpam-krb5 libsasl2-gssapi-mit heimdal-clients

vorbereitung: domain name service

config im dns (da gibts uebrigens auch welche mit ldap/sql backend ;):

aka "srv records rock! - for kerberos but not for ldap :("

config file /etc/krb5.conf auf allen hosts ident!

was ist ein "canonical hostname"?

zonefile mm-karton.com (snippet):

$ORIGIN mm-karton.com.
kerberos                A       10.128.0.24
kerberos-1              A       10.128.0.25
ldap                    CNAME   srv-vie-26.vie.mm-karton.com.
ldap-1                  CNAME   srv-vie-27.vie.mm-karton.com.

_kerberos               TXT     "MM-KARTON.COM"
_kerberos-master._tcp   SRV     10 1 88 kerberos
_kerberos-master._udp   SRV     10 1 88 kerberos
_kpasswd._udp           SRV     10 1 464 kerberos
_kerberos-adm._tcp      SRV     10 1 749 kerberos
_kerberos._tcp          SRV     10 1 88 kerberos
_kerberos._udp          SRV     10 1 88 kerberos
_kerberos._tcp          SRV     20 1 88 kerberos-1
_kerberos._udp          SRV     20 1 88 kerberos-1

_ldap._tcp              SRV     10 1 88 ldap
_ldap._tcp              SRV     20 1 88 ldap-1

zonefile mm-karton.net (snippet), afaik heimdal specific:

_kerberos               TXT             "MM-KARTON.COM"

config am server

/etc/ldap/slapd.conf

# This is the main slapd configuration file. See slapd.conf(5) for more
# info on the configuration options.

#######################################################################
# Global Directives:

include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema

include         /etc/ldap/schema/hdb.schema


TLSCACertificateFile /etc/ldap/ca_crt.pem
TLSCertificateFile /etc/ldap/ldap.mm-karton.com_crt.pem
TLSCertificateKeyFile /etc/ldap/ldap.mm-karton.com_key.pem
TLSCipherSuite HIGH:MEDIUM:+SSLv2


pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd/slapd.args

loglevel        0

modulepath      /usr/lib/ldap
moduleload      back_bdb
moduleload      syncprov

# The maximum number of entries that is returned for a search operation
sizelimit 500




#######################################################################
# Specific Backend Directives for bdb:

backend         bdb
checkpoint 512 30



#######################################################################
# main database
database       bdb
suffix         "dc=mm-karton,dc=com"
rootdn         "cn=ldapmaster@mm-karton.com,dc=mm-karton,dc=com"

directory      "/var/lib/ldap"
dbconfig set_cachesize 0 33554432 0
lastmod         on


index objectClass eq
index   cn,uid,displayName eq,sub,pres
index   krb5PrincipalName eq
index associatedDomain pres,eq,sub
index entryUUID,default,entryCSN eq


# needed for syncrepl
overlay syncprov
syncprov-checkpoint 100 10
syncprov-sessionlog 100

limits dn.exact="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited






#######################################################################
# sasl config

sasl-secprops minssf=0
security simple_bind=64

sasl-regexp
    uid=(.+),cn=.+,cn=auth
    ldap:///dc=mm-karton,dc=com??sub?(|(uid=$1)(krb5PrincipalName=$1@MM-KARTON.COM))
sasl-regexp "=0" "cn=ldapmaster@mm-karton.com,dc=mm-karton,dc=com"




#######################################################################
# access control

# needed for certain auth stuff
access to dn.base="" by * read
access to dn.base="cn=Subschema" by * read

access to attrs=krb5PrincipalName
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read
    by anonymous auth

access to attrs=userPassword
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read
    by anonymous auth



# Kerberos attributes only accessible to root/ldapmaster and the superadmins
access to attrs=krb5KeyVersionNumber,krb5PrincipalRealm,krb5EncryptionType,krb5KDCFlags,krb5Key,krb5MaxLife,krb5MaxRenew,krb5PasswordEnd,krb5ValidEnd,krb5ValidStart,krb5RealmName
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read
    by * none



# user info readable for nssproxy user
access to dn.subtree="ou=users,dc=mm-karton,dc=com"
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read
    by dn="uid=nssproxy,dc=mm-karton,dc=com" read
access to dn.subtree="ou=groups,dc=mm-karton,dc=com"
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read
    by dn="uid=nssproxy,dc=mm-karton,dc=com" read
access to attrs=uid,uidNumber,gidNumber,gecos,homeDirectory,loginShell,memberUid
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read
    by dn="uid=nssproxy,dc=mm-karton,dc=com" read



# all the rest
access to dn.subtree="dc=mm-karton,dc=com"
    by dn="cn=unki@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=lefant@mm-karton.com,dc=mm-karton,dc=com" write
    by dn="cn=ldap/srv-vie-27.vie.mm-karton.com@mm-karton.com,ou=kdc,dc=mm-karton,dc=com" read

/etc/default/slapd

# Default location of the slapd.conf file
SLAPD_CONF=

# System account to run the slapd server under. If empty the server
# will run as root.
SLAPD_USER="openldap"

# System group to run the slapd server under. If empty the server will
# run in the primary group of its user.
SLAPD_GROUP="openldap"

# Path to the pid file of the slapd server. If not set the init.d script
# will try to figure it out from $SLAPD_CONF (/etc/ldap/slapd.conf)
SLAPD_PIDFILE=

# Configure if the slurpd daemon should be started. Possible values:
# - yes:   Always start slurpd
# - no:    Never start slurpd
# - auto:  Start slurpd if a replica option is found in slapd.conf (default)
SLURPD_START=auto

# slapd normally serves ldap only on all TCP-ports 389. slapd can also
# service requests on TCP-port 636 (ldaps) and requests via unix
# sockets.
# Example usage:
SLAPD_SERVICES="ldap://10.128.4.36/ ldapi:///"

# Additional options to pass to slapd and slurpd
SLAPD_OPTIONS=""
SLURPD_OPTIONS=""

export KRB5_KTNAME="FILE:/etc/ldap/ldap.keytab"

[ -L /var/run/ldapi ] || ln -s /var/run/slapd/ldapi /var/run/ldapi

/etc/heimdal-kdc/kadmin.acl

lefant/admin@MM-KARTON.COM all

/etc/heimdal-kdc/kdc.conf

[kdc]
   database = {
      realm = MM-KARTON.COM
      dbname = ldap:dc=mm-karton,dc=com
      mkey_file = /var/lib/heimdal-kdc/m-key
      acl_file = /etc/heimdal-kdc/kadmind.acl
   }
   addresses = 10.128.0.24
$ sudo kadmin -l
init MY.REALM
add lefant/admin

config am host

/etc/libnss-ldap.conf

BASE    dc=mm-karton, dc=com
URI     ldap://ldap.mm-karton.com/,ldap://ldap-1.mm-karton.com/

ldap_version 3
ssl start_tls
tls_cacertfile /etc/ssl/certs/mmagca_crt.pem

binddn uid=nssproxy,dc=mm-karton,dc=com
bindpw XXXXXXXX

scope sub
pam_filter objectClass=posixAccount
nss_base_passwd ou=users,dc=mm-karton,dc=com
nss_base_group ou=groups,dc=mm-karton,dc=com

# Search timelimit
timelimit 10

# Bind/connect timelimit
bind_timelimit 2

pam_min_uid 10000
pam_max_uid 11000

nss_reconnect_tries 1
nss_reconnect_sleeptime 1
nss_reconnect_maxsleeptime 2
nss_reconnect_maxconntries 3
nss_initgroups_ignoreusers arpwatch,asterisk,backup,bin,bind,clamav,cricket,daemon,Debian-exim,debianmirror,dovecot,fetchmail,ftp,games,gnats,identd,irc,list,lp,mail,man,messagebus,mysql,nagios,news,nobody,ntp,ntpd,nut,openvpn,pdns,proftpd,proxy,puppet,root,smmsp,smmta,smsd,snmp,snort,sshd,statd,sync,sys,uucp,www-data,zope

/etc/nsswitch.conf

passwd:         files ldap
group:          files ldap
shadow:         files

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

/etc/krb5.conf

[libdefaults]
   default_realm = MM-KARTON.COM
   dns_lookup_realm = yes

[logging]
        default = SYSLOG:NOTICE:DAEMON
        kdc = FILE:/var/log/kdc.log
        kadmind = FILE:/var/log/kadmind.log

[appdefaults]
        pam = {
                ticket_lifetime = 10h
                renew_lifetime = 10h
                forwardable = true
                proxiable = false
                retain_after_close = false
                minimum_uid = 0
                debug = false
        }

[domain_realm]
   srv-pof-30.pof.mmk.mmdom.net = MM-KARTON.COM

[realms]
   MMK.MMDOM.NET = {
      kdc = DC-VIE-50
      kpasswd_server = DC-VIE-50
      auth_to_local_names = {
         lefant = invaliduser
         unki = invaliduser
      }
   }
   MM-KARTON.COM = {
      admin_server = kerberos.mm-karton.com
      auth_to_local = RULE:[1:$1@$0](^.*@MMK.MMDOM.NET$)s/@MMK.MMDOM.NET//
      auth_to_local = DEFAULT
   }

/etc/pam.d/common-account

account required        pam_access.so
account sufficient      pam_krb5.so forwardable realm=MMK.MMDOM.NET minimum_uid=20000
account sufficient      pam_krb5.so forwardable realm=MM-KARTON.COM minimum_uid=20000
account required        pam_unix.so

/etc/pam.d/common-auth

auth    optional        pam_group.so
auth    sufficient      pam_krb5.so forwardable realm=MMK.MMDOM.NET minimum_uid=20000 try_first_pass
auth    sufficient      pam_krb5.so forwardable realm=MM-KARTON.COM minimum_uid=20000 try_first_pass
auth    required        pam_unix.so try_first_pass

/etc/pam.d/common-session

session required pam_mkhomedir.so umask=0022 skel=/etc/mmskel
session sufficient pam_krb5.so forwardable realm=MMK.MMDOM.NET minimum_uid=20000
session sufficient pam_krb5.so forwardable realm=MM-KARTON.COM minimum_uid=20000
session required        pam_unix.so

restrict logins to certain users:

/etc/security/access.conf

# first, to avoid delays when network is still unavailable
+:ALL:LOCAL
+:root:ALL

# remote users and groups
+:bofh:ALL

# deny everything else
-:ALL:ALL

/etc/adduser.conf (snippet)

# FIRST_[GU]ID to LAST_[GU]ID inclusive is the range of UIDs of dynamically
# allocated user accounts/groups.
FIRST_UID=1000
LAST_UID=19999

ldap client config (administration):

/etc/ldap/ldap.conf

BASE    dc=mm-karton, dc=com
URI     ldap://ldap.mm-karton.com/
ssl start_tls
tls_cacert /etc/ssl/certs/ca_crt.pem

ldapwhoami, ldapsearch

sudo, nopasswd, weil solches haben wir ja nicht...

/etc/sudoers

lefant ALL=(ALL) NOPASSWD:ALL

single sign on fuer applikationen (gssapi support, das grosse fragezeichen)

/etc/ssh/sshd_config (snippet)

GSSAPIAuthentication yes
GSSAPIKeyExchange yes

/etc/ssh/ssh_config (snippet)

host *
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials yes
    GSSAPITrustDns yes

firefox: out-of-the-box!

apache: (apt-get install libapache2-mod-auth-kerb) config snippet

   <Location />
      AuthType Kerberos
      AuthName "MM Login (use windows login *without* mm\ prefix)"
      KrbServiceName HTTP
      Krb5Keytab /etc/apache2/keytab
      KrbAuthRealms MMK.MMDOM.NET MM-KARTON.COM
      AuthGroupFile /etc/wwwusers
      Require group NocUsers
      Order deny,allow
      Deny from all
      Allow from noc.mm-karton.com
      Satisfy any
   </Location>

misc stuff

  • tcpdump
  • strace
  • $HOME/.k5login