Saturday, December 29, 2018

389 Directory Server 1.3.x Password Policy

389 Directory Server 1.3.x Password Policy

Last time we installed 389-ds and did some basic configuration, see 389 Directory Server 1.3.x on Red Hat Enterprise Linux 7.6.

Let's implement a password policy now. We have the following requirements:

  • Password Minimum Length: 8
  • Maximum Password Failures: 100
  • Reset Password Failure Count After: 30 days
  • Password Must Change: yes (we want our users to change their password when they first bind to the directory server or when the password has been reset by the Manager DN)
  • Password Storage Scheme: we want the strongest, which is currently PBKDF2_SHA256 with 30,000 iterations

Let's enforce those rules:

dirsrv@ldap01 $ ldapmodify -D "cn=Directory Manager" -y /etc/dirsrv/.dmpw -x -ZZ
dn: cn=config
changetype: modify
replace: passwordCheckSyntax
passwordCheckSyntax: on
-
replace: passwordLockout
passwordLockout: on
-
replace: passwordMaxFailure
passwordMaxFailure: 100
-
replace: passwordMinCategories
passwordMinCategories: 1
-
replace: passwordMinLength
passwordMinLength: 8
-
replace: passwordResetFailureCount
passwordResetFailureCount: 2592000
-
replace: passwordMustChange
passwordMustChange: on
-
replace: passwordStorageScheme
passwordStorageScheme: PBKDF2_SHA256
-
replace: passwordTrackUpdateTime
passwordTrackUpdateTime: on
-
replace: passwordUnlock
passwordUnlock: off
-
replace: nsslapd-rootpwstoragescheme
nsslapd-rootpwstoragescheme: PBKDF2_SHA256
^D
modifying entry "cn=config"

This should make us comply (well mostly) with NIST's Special Publication 800-63 Digital Identity Guidelines.

If you have more strict password rules (like passwords can only be changed after xx hours), don't forget to add your directory admins to the passwordAdminDN role to bypass those rules:

dirsrv@ldap01 $ ldapmodify -D "cn=Directory Manager" -y /etc/dirsrv/.dmpw -x -ZZ
dn: cn=config
changetype: modify
replace: passwordAdminDN
passwordAdminDN: cn=Directory Administrators,ou=Groups,dc=unix,dc=mycompany,dc=com
^D

Read the next part here 389 Directory Server 1.3.x Users, Groups and ACIs.

Links

Friday, December 28, 2018

389 Directory Server 1.3.x on Red Hat Enterprise Linux 7.6

389 Directory Server 1.3.x on Red Hat Enterprise Linux 7.6

Well you know the saying, all good things must come to an end. So we're going to replace Oracle's DSEE with 389 Directory Server today.

To get started we need to install 389-ds and do a silent setup:

[root@ldap01~]# yum -y install 389-ds-base
Loaded plugins: ulninfo
Resolving Dependencies
--> Running transaction check
---> Package 389-ds-base.x86_64 0:1.3.8.4-18.el7_6 will be installed
...

[root@ldap01~]# cat << EOF > /etc/sudoers.d/dirsrv
dirsrv $(hostname -s) = (root) NOPASSWD: /bin/systemctl start dirsrv@$(hostname -s), \
  /bin/systemctl stop dirsrv@$(hostname -s), \
  /bin/systemctl restart dirsrv@$(hostname -s)
EOF
[root@ldap01~]# chmod 440 /etc/sudoers.d/dirsrv
[root@ldap01~]# visudo -c

[root@ldap01~]# pwmake 192 | tr -d '\n' > /etc/dirsrv/.dmpw
[root@ldap01~]# chown dirsrv:dirsrv /etc/dirsrv/.dmpw
[root@ldap01~]# chmod 400 /etc/dirsrv/.dmpw

[root@ldap01~]# cat << EOF > /tmp/userRoot.ldif
dn: dc=unix,dc=mycompany,dc=com
objectClass: top
objectClass: domain
# https://tools.ietf.org/html/rfc4519
#  The 'dc' ('domainComponent' in RFC 1274) attribute type is a string
# holding one component, a label, of a DNS domain name.
# Examples: Valid values include "example" and "com" but not
# "example.com". The latter is invalid as it contains multiple
# domain components.
dc: unix
aci: (targetattr != "userPassword")(version 3.0;acl "Anonymous read-search acc
 ess"; allow (read, search, compare)(userdn = "ldap:///anyone");)
aci: (targetattr = "*")(version 3.0; acl "allow all Admin group"; allow(all) g
 roupdn = "ldap:///cn=Directory Administrators,ou=Groups,dc=mycompany,dc=com";
 )

dn: ou=Groups,dc=unix,dc=mycompany,dc=com
objectclass: top
objectclass: organizationalUnit
ou: Groups

dn: cn=Directory Administrators,ou=Groups,dc=unix,dc=mycompany,dc=com
objectClass: top
objectClass: groupOfUniqueNames
cn: Directory Administrators
ou: Groups
uniqueMember: cn=Directory Manager

dn: ou=People,dc=unix,dc=mycompany,dc=com
objectClass: top
objectClass: organizationalUnit
ou: People
aci: (targetattr = "gecos || loginShell || userPassword")(version 3.0;acl "All
 ow self entry modification";allow (write)(userdn = "ldap:///self");)

dn: ou=Special Users,dc=unix,dc=mycompany,dc=com
objectClass: top
objectClass: organizationalUnit
ou: Special Users
description: Special Administrative Accounts
EOF

[root@ldap01~]# cat << EOF > /tmp/setup.inf
[General]
FullMachineName=$(hostname -f)
StrictHostCheck=true
SuiteSpotGroup=dirsrv
SuiteSpotUserID=dirsrv

[slapd]
AddSampleEntries=No
InstallLdifFile=/tmp/userRoot.ldif
RootDN=cn=Directory Manager
RootDNPwd=$(pwdhash -s PBKDF2_SHA256 $(< /etc/dirsrv/.dmpw))
SchemaFile=/usr/share/dirsrv/data/60rfc4876.ldif
ServerIdentifier=$(hostname -s)
ServerPort=389
Suffix=dc=unix,dc=mycompany,dc=com
UseExistingMC=0
EOF

[root@ldap01~]# setup-ds.pl -s -f /tmp/setup.inf
...
Your new DS instance 'ldap01' was successfully created.
[root@ldap01~]# systemctl enable dirsrv@$(hostname -s)

We want a STARTTLS/LDAPS only server, so we need to create a CA, certificate and a key. See nginx on Solaris 11.3 SRU 19 with EC crypto and HTTP/2 support for how to do that with OpenSSL or How to create a SSL CA/certificate/key with pktool. I will just use the ECC files for now but I'm pretty sure I'll need all of them for older, non ECC clients.

Either way, you should have the following files now: CA.crt, server.crt, server.key and/or server-ecc.crt, server-ecc.key.

[root@ldap01~]# su -m dirsrv
dirsrv@ldap01 $ ldapadd -D "cn=Directory Manager" -xy /etc/dirsrv/.dmpw -h localhost -p 389
# enable the RSA cipher family,
# setting the NSS database security device,
# and the server certificate nickname
dn: cn=RSA,cn=encryption,cn=config
changetype: add
objectClass: top
objectClass: nsEncryptionModule
nsSSLPersonalitySSL: server-cert
nsSSLActivation: on
nsSSLToken: internal (software)
cn: RSA

# Enable TLS, tweak some defaults and sprinkle some security settings
dn: cn=config
changetype: modify
replace: nsslapd-security
nsslapd-security: on
-
# Preventing Directory Server to Start If the Certificate Has Been Expired
replace: nsslapd-validate-cert
nsslapd-validate-cert: on
-
# require simple binds to occur over a secure connection (SSL/TLS or Start TLS)
replace: nsslapd-require-secure-binds
nsslapd-require-secure-binds: on
-
# Disable anon binds except for the root dse
replace: nsslapd-allow-anonymous-access
nsslapd-allow-anonymous-access: rootdse
-
# A file descriptor is used whenever a client connects to the server
# and also for some server activities, such as index maintenance.
replace: nsslapd-maxdescriptors
nsslapd-maxdescriptors: 16384
-
replace: nsslapd-listen-backlog-size
nsslapd-listen-backlog-size: 256

# only accept TLS 1.2 connections
# leave the TLS1.0 default for older clients
# such as RHEL6, SLES11, Solaris 10!
dn: cn=encryption,cn=config
changetype: modify
replace: sslVersionMin
sslVersionMin: TLS1.2

dn: cn=config
changetype: modify
# Set a minimum SSF to disable insecure connections to a directory
# XXX changing the SSF has effects immediately!
# only change this at the very end or the ldapadd connection will drop!
replace: nsslapd-minssf
nsslapd-minssf: 128
^D

dirsrv@ldap01 $ sudo systemctl stop dirsrv@$(hostname -s)

dirsrv@ldap01 $ NSSPW="$(pwmake 192)"
dirsrv@ldap01 $ echo -n "$NSSPW" > /etc/dirsrv/.nsspw
dirsrv@ldap01 $ chmod 400 /etc/dirsrv/.nsspw
dirsrv@ldap01 $ certutil -d /etc/dirsrv/slapd-$(hostname -s)/ -N -f /etc/dirsrv/.nsspw
dirsrv@ldap01 $ chmod 600 /etc/dirsrv/slapd-$(hostname -s)/*.db
dirsrv@ldap01 $ echo -n "Internal (Software) Token:$NSSPW" > /etc/dirsrv/slapd-$(hostname -s)/pin.txt
dirsrv@ldap01 $ chmod 400 /etc/dirsrv/slapd-$(hostname -s)/pin.txt
dirsrv@ldap01 $ touch /etc/dirsrv/slapd-$(hostname -s)/pkcs11.txt
dirsrv@ldap01 $ chmod 600 /etc/dirsrv/slapd-$(hostname -s)/pkcs11.txt
dirsrv@ldap01 $ certutil -d /etc/dirsrv/slapd-$(hostname -s)/ -A -n "CA" -t "CT,," -f /etc/dirsrv/.nsspw -i .../CA.crt
dirsrv@ldap01 $ openssl pkcs12 -export -in .../server-ecc.crt -inkey .../server-ecc.key \
                  -out /tmp/servercert.p12 -name "server-cert" -passout file:/etc/dirsrv/.nsspw
dirsrv@ldap01 $ pk12util -i /tmp/servercert.p12 -d /etc/dirsrv/slapd-$(hostname -s)/ -k /etc/dirsrv/.nsspw -w /etc/dirsrv/.nsspw
pk12util: PKCS12 IMPORT SUCCESSFUL
dirsrv@ldap01 $ certutil -d /etc/dirsrv/slapd-$(hostname -s)/ -V -n "server-cert" -u V
certutil: certificate is valid

[root@ldap01~]# systemctl restart dirsrv@$(hostname -s)
[root@ldap01~]# cp .../CA.crt /etc/openldap/certs/
[root@ldap01~]# cat << EOF > /etc/openldap/ldap.conf
BASE dc=unix,dc=mycompany,dc=com
URI ldap://$(hostname -f)

TLS_CACERT /etc/openldap/certs/CA.crt
TLS_PROTOCOL_MIN 3.3
TLS_REQCERT demand
EOF

dirsrv@ldap01 $ openssl s_client -connect $(hostname -f):389 -starttls ldap -CAfile /etc/openldap/certs/CA.crt < /dev/null
...
    Verify return code: 0 (ok)
dirsrv@ldap01 $ openssl s_client -connect $(hostname -f):636 -CAfile /etc/openldap/certs/CA.crt < /dev/null
...
    Verify return code: 0 (ok)
dirsrv@ldap01 $ ldapsearch -LLL -D "cn=Directory Manager" -xy /etc/dirsrv/.dmpw \
                  -ZZ -s base -b 'cn=encryption,cn=config' sslVersionMin
dn: cn=encryption,cn=config
sslVersionMin: TLS1.2

And that was the first part. Short recap we have installed 389-ds on RHEL, we configured it with our chosen suffix, created a new SSL certificate/key and enabled TLS-only connections to the directory server. Also we did some LDAP client configuration in /etc/openldap/ldap.conf.

Read the next part here 389 Directory Server 1.3.x Password Policy.

Links

389 Directory Server 1.3.x LDAP client authentication

389 Directory Server 1.3.x LDAP client authentication Last time we did a multi-master replication setup, see 389 Directory Server 1.3.x Repl...