Two Factor Authentication is a lofty goal for any linux administrator. If you’re lucky enough to have access to an NetIQ eDirectory server, hardware based two factor authentication is closer than you think.
Tutorial on how to use SSSD (pronounced Triple “S” D) as a cross Linux platform (RHEL, SLES, Ubuntu, et. al) authentication agent instead of painful and often times disparate pam_ldap and sudoers configurations. Centralized user and group management using existing directory infrastructure. Learn how centrally store SSH key and sudoer configurations in LDAP. No more having to copy your SSH key to each new server. Create a SSH Key based single sign on solution. Your sudo commands are authenticated against your Directory. Expand the configuration of SSSD clients for 2 factor authentication using a HOTP configured YubiKey that does not require any changes on the authenticating client. Integration with eDirectory. Explore SSO Kerberized options with Active Directory and MIT Kerberos.
This is based from a presentation I gave at SUSECON 2016 in Washington D.C. Right now it’s fairly unorganized and more as a place to gather my thoughts as I worked through developing my presentaion
Create a Bind Account for SSSD
In this case I’ve created cn=SSSDBInd,ou=service,o=gtopia
This account has read only rights to all the Users container in the tree. This can be limited down to only the required attributes but for the sake of time we’ll skip that. I may come back later and enhance this section.
This will be our user to bind with inside of SSSD because I do not want to allow anonymous searches on the Directory.
You will first need to ensure your LDAP server is capable of secure connections. You will then need the Public self-signed certificate or the Public certificate of your Certificate Authority.
- Find the “Configure Certificate Authority” Task
- Open the certificates tab
- Select the Self Signed RSA Certificate
- Click Export
Save the file, (rename extension as .pem)
Upload the certificate to your client SSSD client.
Make the Certificate available to the whole system
- Copy certificate to /etc/ssl/certs
- Run the Hash Command to make it available in the hashed directory
susehost:/etc/ssl/certs # c_rehash /etc/ssl/certs/
This will rehash all the certificates in that folder and will be useful later.
Now that certificate is available you can configure the system ldap.conf file to use that certificate.
# # LDAP Defaults # # See ldap.conf(5) for details # This file should be world readable but not world writable. #BASE dc=example,dc=com #URI ldap://ldap.example.com ldap://ldap-master.example.com:666 #SIZELIMIT 12 #TIMELIMIT 15 #DEREF never TLS_CACERTDIR /etc/ssl/certs
IF you don’t configure the ldap.conf file you get errors like this
# ldapsearch -H ldaps://ldap.gtopia.org ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1) additional info: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (self signed certificate in certificate chain)
Now you can try a test Search
# ldapsearch -H ldaps://ldap.gtopia.org -x -b o=gtopia -D cn=SSSDBind,ou=service,o=gtopia -W objectclass=inetOrgPerson cn Enter LDAP Password: # extended LDIF # # LDAPv3 # base <o=gtopia> with scope subtree # filter: objectclass=inetOrgPerson # requesting: cn # # SSSDBind, Service, gtopia dn: cn=SSSDBind,ou=Service,o=gtopia cn: SSSDBind # mark, users, gtopia dn: cn=mark,ou=users,o=gtopia cn: mark # search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 2
This shows the server can really talk to LDAP outside of SSSD. Confirms working LDAP and pathing. So troubleshooting from here forward we know is only in SSSD land.
Configure sssd.conf
#pam-config –add –sss –mkhomedir
Add Posix Attributes to LDAP user
The schema must be extended before Attributes can be added, fortunatly the basic schema has been provided.
susehost:/opt/novell/eDirectory/lib64/nds-schema # ndssch -h ldap.gtopia.org -t GTOPIA admin.gtopia rfc2307-usergrou p.sch Password: Logging into the tree as "admin.gtopia". Please Wait ... Extending schema, For more details view schema extension logfile: /root/schema.log NDS schema extension complete.
To do SUDO in sssd we must also extend the schema in LDAP for the SUDO attributes. There is a schema provided that accomplishes this: /etc/openldap/schema/sudo.schema
unfortunatly this schema doesn’t work with the ndssch utility. Probably becuse this file isn’t well formed and not in the right format. Here’s a good LDIF based schema file here:
# # OpenLDAP schema file for Sudo # Save as /etc/openldap/schema/sudo.schema # dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Start of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'An integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) dn: cn=schema changetype: modify add: objectclasses objectclasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description ) )
Once that file is loaded into the ldap server then we can create SUDOERS rules in LDAP.
Check this out as you work on this step: https://www.sudo.ws/readme_ldap.html
Here’s a sample output of creating an LDIF from the sudoers file.
host:~ # export SUDOERS_BASE=ou=Sudoers,o=gtopia host:~ # sudoers2ldif /etc/sudoers dn: cn=defaults,ou=Sudoers,o=gtopia objectClass: top objectClass: sudoRule cn: defaults description: Default sudoOption's go here sudoOption: always_set_home sudoOption: secure_path="/usr/sbin:/usr/bin:/sbin:/bin" sudoOption: env_reset sudoOption: env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS XDG_SESSION_COOKIE" sudoOption: !insults sudoOption: targetpw sudoOrder: 1 dn: cn=ALL,ou=Sudoers,o=gtopia objectClass: top objectClass: sudoRule cn: ALL sudoUser: ALL sudoHost: ALL sudoRunAsUser: ALL sudoCommand: ALL sudoOrder: 2 dn: cn=root,ou=Sudoers,o=gtopia objectClass: top objectClass: sudoRule cn: root sudoUser: root sudoHost: ALL sudoRunAsUser: ALL sudoCommand: ALL sudoOrder: 3
Create a sample user sudo command.
dn: cn=mark,ou=Sudoers,o=gtopia objectClass: top objectClass: sudoRule cn: mark sudoUser: mark sudoHost: ALL sudoRunAsUser: ALL sudoCommand: ALL sudoOption: !authenticate sudoOrder: 3
Here is the sssd.conf
[sssd] config_file_version = 2 services = nss, pam, sudo # SSSD will not start if you do not configure any domains. # Add new domain configurations as [domain/<NAME>] sections, and # then add the list of domains (in the order you want them to be # queried) to the "domains" attribute below and uncomment it. domains = LDAP [nss] [pam] # Example LDAP domain [domain/LDAP] id_provider = ldap auth_provider = ldap # ldap_schema can be set to "rfc2307", which stores group member names in the # "memberuid" attribute, or to "rfc2307bis", which stores group member DNs in # the "member" attribute. If you do not know this value, ask your LDAP # administrator. ldap_schema = rfc2307bis ldap_uri = ldaps://ldap.gtopia.org:636 ldap_search_base = ou=users,o=gtopia ldap_tls_cacertdir = /etc/ssl/certs create_homedir = true ldap_default_bind_dn = cn=SSSDBind,ou=service,o=gtopia ldap_default_authtok_type = password ldap_default_authtok = ***** #SUDOERS sudo_provider = ldap ldap_sudo_search_base = ou=sudoers,o=gtopia #ldap_sudorule_object_class = sudoRole sudoers_debug = 2 ldap_sudo_hostnames = client1.gtopia.org
Configuring SSH Keys in LDAP
Unless you’re using IPA, sshkeys in ldap cannot be done via sssd. There is a very useful readme included.
debug: /usr/lib/ssh/ssh-ldap-helper -v -dd -s mark
Here is the Schema file suitable for loading sshPublicKeys into eDirectory.
dn: cn=schema changetype: modify add: attributetypes attributetypes: ( 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 ) dn: cn=schema changetype: modify add: objectclasses objectclasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MUST ( sshPublicKey $ uid ) )
You must configure an ldap.conf specifically for ssh. This is useful in case something else mucks around with the openldap/ldap.conf file Here is all I needed in the /etc/ssh/ldap.conf
uri ldaps://ldap.gtopia.org binddn cn=SSSDBind,ou=service,o=gtopia bindpw ****** base ou=users,o=gtopia scope sub tls_cacertdir /etc/ssl/certs
Add these lines to sshd_config
#AuthorizedKeysCommand none AuthorizedKeysCommand /usr/lib/ssh/ssh-ldap-wrapper AuthorizedKeysCommandUser nobody AuthorizedKeysFile .ssh/authorized_keys
Test with the built in tools
~ # /usr/lib/ssh/ssh-ldap-helper -w -vv -dd -s mark debug1: Reading configuration data /etc/ssh/ldap.conf debug1: LDAP do connect debug2: LDAP do connect OK debug1: LDAP process user ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEA47di4ZmNoSWgFkjmaDry389Slhg7res4oploixROi8nL3CT3FsR9QzOrTuzOFuhZRkA5XMnh+QPXw6gX7xQJrktdm09QK5rblfZYLdAGdCpWYy2H1D79Ebbbrkm4dR/9GJJ5kAqBVV07Pn/LJCzaZ2l8E1pVLfz8JInW29aDTGdUG0s9C2loItSacA9K5A7lLrzrGQ3HTpD8+0SR0DQRG+sTpUJxwbrrHAFKRDvN8iy3STtP07jvzWrlJlIMHQ3QTY8sGORfrahQdZM2rhTnToDWyw+w/sBuVMZTJoftjcZVWw3El8mgWFvLoz3FKia7pMYN4cfxXDdpnSHiEbb23/DBdfyBPuILiDSgofJEJVJsU+xRAo4M8LpWSndN5ZJKSOAvpN6OWFx663auXRBYGAmPcnIgB9ZrYq79Xvf2+K7n9KYoskruQ6qjNPw1IDXTdJL4cqbJtcNqT8YIFGGu3pDwGfa/g1XXRj8GMH0nTN+Sysl2chz7pNiO4kBUwZD+PrPIeM+5gS8ObJ340bgHfvjE3IL33koh8glHmFGY9I1IP854Um3wk32lFPcJAIOgAlG98Wlr+XvAP7lzHAZUg1ak5BTlrKJTamsfEjLfAWMbrmTLeKmrdXQ4uDfJnxB7QYRQx6//p9ObLqrjOAizrJVaGOuNcOPFMMr7PDtFZts= Default debug2: LDAP process user finished debug1: LDAP do close debug2: LDAP do close OK