{"id":693,"date":"2018-10-18T12:07:02","date_gmt":"2018-10-18T12:07:02","guid":{"rendered":"https:\/\/www.appservgrid.com\/paw92\/?p=693"},"modified":"2018-10-18T15:53:04","modified_gmt":"2018-10-18T15:53:04","slug":"configure-openldap-master-slave-replication-with-puppet-lisenet-com-linux-security","status":"publish","type":"post","link":"https:\/\/www.appservgrid.com\/paw92\/index.php\/2018\/10\/18\/configure-openldap-master-slave-replication-with-puppet-lisenet-com-linux-security\/","title":{"rendered":"Configure OpenLDAP Master\/Slave Replication with Puppet | Lisenet.com :: Linux | Security"},"content":{"rendered":"<p>We\u2019re going to use Puppet to configure a pair of OpenLDAP servers with a master-slave replication.<\/p>\n<p>This article is part of the <a href=\"https:\/\/www.lisenet.com\/2018\/homelab-project-with-kvm-katello-and-puppet\/\" target=\"_blank\" rel=\"noopener\">Homelab Project with KVM, Katello and Puppet<\/a> series.<\/p>\n<h2>Homelab<\/h2>\n<p>We have two CentOS 7 servers installed which we want to configure as follows:<\/p>\n<p>ldap1.hl.local (10.11.1.11) \u2013 will be configured as an LDAP master<br \/>\nldap2.hl.local (10.11.1.12) \u2013 will be configured as an LDAP slave<\/p>\n<p>Both servers have SELinux set to enforcing mode.<\/p>\n<p>See the image below to identify the homelab part this article applies to.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lisenet.com\/wp-content\/uploads\/2018\/04\/lisenet-homelab-diagram_ldap.png\" alt=\"\" width=\"1200\" height=\"793\" \/><\/p>\n<h2>Configuration with Puppet<\/h2>\n<p>Puppet master runs on the <a href=\"https:\/\/www.lisenet.com\/2016\/install-katello-on-centos-7\/\" target=\"_blank\" rel=\"noopener\">Katello<\/a> server. We use <a href=\"https:\/\/forge.puppet.com\/camptocamp\/openldap\" target=\"_blank\" rel=\"noopener\">camptocamp-openldap<\/a> Puppet module to configure OpenLDAP. Please see the module documentation for features supported and configuration options available.<\/p>\n<p>See <a href=\"https:\/\/www.lisenet.com\/2016\/openldap-with-ssl-and-nfs-for-user-home-directories-on-centos-7\/\" target=\"_blank\" rel=\"noopener\">here<\/a> (CentOS 7) and <a href=\"https:\/\/www.lisenet.com\/2014\/install-and-configure-an-openldap-server-with-ssl-on-debian-wheezy\/\" target=\"_blank\" rel=\"noopener\">here<\/a> (Debian) for blog posts on how to configure an OpenLDAP server manually.<\/p>\n<p>Note that instructions below apply to both LDAP servers.<\/p>\n<p>Firewall configuration to allow LDAPS access from homelab LAN:<\/p>\n<p>firewall { &#8216;007 allow LDAPS&#8217;:<br \/>\ndport =&gt; [636],<br \/>\nsource =&gt; &#8216;10.11.1.0\/24&#8217;,<br \/>\nproto =&gt; tcp,<br \/>\naction =&gt; accept,<br \/>\n}<\/p>\n<p>Ensure that the private key (which we created previously) in the PKCS#8 format is available.<\/p>\n<p>file {&#8216;\/etc\/pki\/tls\/private\/hl.pem&#8217;:<br \/>\nensure =&gt; file,<br \/>\nsource =&gt; &#8216;puppet:\/\/\/homelab_files\/hl.pem&#8217;,<br \/>\nowner =&gt; &#8216;0&#8217;,<br \/>\ngroup =&gt; &#8216;ldap&#8217;,<br \/>\nmode =&gt; &#8216;0640&#8217;,<br \/>\n}<\/p>\n<p>Configure the LDAP server (note how we bind to the SSL port):<\/p>\n<p>class { &#8216;openldap::server&#8217;:<br \/>\nldap_ifs =&gt; [&#8216;127.0.0.1:389\/&#8217;],<br \/>\nldaps_ifs =&gt; [&#8216;0.0.0.0:636\/&#8217;],<br \/>\nssl_cert =&gt; &#8216;\/etc\/pki\/tls\/certs\/hl.crt&#8217;,<br \/>\nssl_key =&gt; &#8216;\/etc\/pki\/tls\/private\/hl.pem&#8217;,<br \/>\n}<\/p>\n<p>Configure the database:<\/p>\n<p>openldap::server::database { &#8216;dc=top&#8217;:<br \/>\nensure =&gt; present,<br \/>\ndirectory =&gt; &#8216;\/var\/lib\/ldap&#8217;,<br \/>\nsuffix =&gt; &#8216;dc=top&#8217;,<br \/>\nrootdn =&gt; &#8216;cn=admin,dc=top&#8217;,<br \/>\nrootpw =&gt; &#8216;cGfSAyREZC5XnJa77iP+EdR8BrvZfUuo&#8217;,<br \/>\n}<\/p>\n<p>Configure schemas:<\/p>\n<p>openldap::server::schema { &#8216;cosine&#8217;:<br \/>\nensure =&gt; present,<br \/>\npath =&gt; &#8216;\/etc\/openldap\/schema\/cosine.schema&#8217;,<br \/>\n}<br \/>\nopenldap::server::schema { &#8216;inetorgperson&#8217;:<br \/>\nensure =&gt; present,<br \/>\npath =&gt; &#8216;\/etc\/openldap\/schema\/inetorgperson.schema&#8217;,<br \/>\nrequire =&gt; Openldap::Server::Schema[&#8220;cosine&#8221;],<br \/>\n}<br \/>\nopenldap::server::schema { &#8216;nis&#8217;:<br \/>\nensure =&gt; present,<br \/>\npath =&gt; &#8216;\/etc\/openldap\/schema\/nis.ldif&#8217;,<br \/>\nrequire =&gt; Openldap::Server::Schema[&#8220;inetorgperson&#8221;],<br \/>\n}<\/p>\n<p>Configure ACLs:<\/p>\n<p>$homelab_acl = {<br \/>\n&#8216;0 to attrs=userPassword,shadowLastChange&#8217; =&gt; [<br \/>\n&#8216;by dn=&#8221;cn=admin,dc=top&#8221; write&#8217;,<br \/>\n&#8216;by dn=&#8221;cn=reader,dc=top&#8221; read&#8217;,<br \/>\n&#8216;by self write&#8217;,<br \/>\n&#8216;by anonymous auth&#8217;,<br \/>\n&#8216;by * none&#8217;,<br \/>\n],<br \/>\n&#8216;1 to dn.base=&#8221;&#8221;&#8216; =&gt; [<br \/>\n&#8216;by * read&#8217;,<br \/>\n],<br \/>\n&#8216;2 to *&#8217; =&gt; [<br \/>\n&#8216;by dn=&#8221;cn=admin,dc=top&#8221; write&#8217;,<br \/>\n&#8216;by dn=&#8221;cn=reader,dc=top&#8221; read&#8217;,<br \/>\n&#8216;by self write&#8217;,<br \/>\n&#8216;by users read&#8217;,<br \/>\n&#8216;by anonymous auth&#8217;,<br \/>\n&#8216;by * none&#8217;,<br \/>\n],<br \/>\n}<br \/>\nopenldap::server::access_wrapper { &#8216;dc=top&#8217; :<br \/>\nacl =&gt; $homelab_acl,<br \/>\n}<\/p>\n<p>Base configuration:<\/p>\n<p>file { &#8216;\/root\/.ldap_config.ldif&#8217;:<br \/>\nensure =&gt; file,<br \/>\nsource =&gt; &#8216;puppet:\/\/\/homelab_files\/ldap_config.ldif&#8217;,<br \/>\nowner =&gt; &#8216;0&#8217;,<br \/>\ngroup =&gt; &#8216;0&#8217;,<br \/>\nmode =&gt; &#8216;0600&#8217;,<br \/>\nnotify =&gt; Exec[&#8216;configure_ldap&#8217;],<br \/>\n}<br \/>\nexec { &#8216;configure_ldap&#8217;:<br \/>\ncommand =&gt; &#8216;ldapadd -c -x -D cn=admin,dc=top -w PleaseChangeMe -f \/root\/.ldap_config.ldif &amp;&amp; touch \/root\/.ldap_config.done&#8217;,<br \/>\npath =&gt; &#8216;\/usr\/bin:\/usr\/sbin:\/bin:\/sbin&#8217;,<br \/>\nprovider =&gt; shell,<br \/>\nonlyif =&gt; [&#8216;test -f \/root\/.ldap_config.ldif&#8217;],<br \/>\nunless =&gt; [&#8216;test -f \/root\/.ldap_config.done&#8217;],<br \/>\n}<\/p>\n<p>Content of the file ldap_config.ldif can be seen below.<\/p>\n<p>We create a read-only account cn=reader,dc=top for LDAP replication, we also create an LDAP user uid=tomas,ou=Users,dc=hl.local,dc=top to log into homelab servers.<\/p>\n<p>dn: cn=reader,dc=top<br \/>\nobjectClass: simpleSecurityObject<br \/>\nobjectclass: organizationalRole<br \/>\ndescription: LDAP Read-only Access<br \/>\nuserPassword: NrBn6Kd4rW8jmf+KWmfbTMFOkcC43ctF<\/p>\n<p>dn: dc=hl.local,dc=top<br \/>\no: hl.local<br \/>\ndc: hl.local<br \/>\nobjectClass: dcObject<br \/>\nobjectClass: organization<\/p>\n<p>dn: ou=Users,dc=hl.local,dc=top<br \/>\nobjectClass: organizationalUnit<br \/>\nou: Users<\/p>\n<p>dn: uid=tomas,ou=Users,dc=hl.local,dc=top<br \/>\nuid: tomas<br \/>\nuidNumber: 5001<br \/>\ngidNumber: 5001<br \/>\nobjectClass: top<br \/>\nobjectClass: person<br \/>\nobjectClass: inetOrgPerson<br \/>\nobjectClass: posixAccount<br \/>\nobjectClass: shadowAccount<br \/>\nuserPassword: aBLnLxAUZAqwwII6fNUzizyOY\/YAowtt<br \/>\ncn: Tomas<br \/>\ngn: Tomas<br \/>\nsn: Admin<br \/>\nmail: <a href=\"\/cdn-cgi\/l\/email-protection\">[email protected]<\/a><br \/>\nshadowLastChange: 16890<br \/>\nshadowMin: 0<br \/>\nshadowMax: 99999<br \/>\nshadowWarning: 14<br \/>\nshadowInactive: 3<br \/>\nloginShell: \/bin\/bash<br \/>\nhomeDirectory: \/home\/guests\/tomas<\/p>\n<p>dn: ou=Groups,dc=hl.local,dc=top<br \/>\nobjectClass: organizationalUnit<br \/>\nou: Groups<\/p>\n<p>dn: cn=tomas,ou=Groups,dc=hl.local,dc=top<br \/>\ngidNumber: 5001<br \/>\nobjectClass: top<br \/>\nobjectClass: posixGroup<br \/>\ncn: tomas<\/p>\n<h3>LDAP Master Server<\/h3>\n<p>Configure sync provider on the master node:<\/p>\n<p>file { &#8216;\/root\/.ldap_syncprov.ldif&#8217;:<br \/>\nensure =&gt; file,<br \/>\nsource =&gt; &#8216;puppet:\/\/\/homelab_files\/ldap_syncprov.ldif&#8217;,<br \/>\nowner =&gt; &#8216;0&#8217;,<br \/>\ngroup =&gt; &#8216;0&#8217;,<br \/>\nmode =&gt; &#8216;0600&#8217;,<br \/>\nnotify =&gt; Exec[&#8216;configure_syncprov&#8217;],<br \/>\n}<br \/>\nexec { &#8216;configure_syncprov&#8217;:<br \/>\ncommand =&gt; &#8216;ldapadd -c -Y EXTERNAL -H ldapi:\/\/\/ -f \/root\/.ldap_syncprov.ldif &amp;&amp; touch \/root\/.ldap_syncprov.done &amp;&amp; systemctl restart slapd&#8217;,<br \/>\npath =&gt; &#8216;\/usr\/bin:\/usr\/sbin:\/bin:\/sbin&#8217;,<br \/>\nprovider =&gt; shell,<br \/>\nonlyif =&gt; [<br \/>\n&#8216;test -f \/root\/.ldap_syncprov.ldif&#8217;,<br \/>\n&#8216;test -f \/root\/.ldap_config.done&#8217;<br \/>\n],<br \/>\nunless =&gt; [&#8216;test -f \/root\/.ldap_syncprov.done&#8217;],<br \/>\n}<\/p>\n<p>Content of the file ldap_syncprov.ldif for the master server can be seen below.<\/p>\n<p>dn: cn=module,cn=config<br \/>\nobjectClass: olcModuleList<br \/>\ncn: module<br \/>\nolcModulePath: \/usr\/lib64\/openldap<br \/>\nolcModuleLoad: syncprov.la<\/p>\n<p>dn: olcOverlay=syncprov,olcDatabase=hdb,cn=config<br \/>\nobjectClass: olcOverlayConfig<br \/>\nobjectClass: olcSyncProvConfig<br \/>\nolcOverlay: syncprov<br \/>\nolcSpSessionLog: 100<\/p>\n<h3>LDAP Slave Server<\/h3>\n<p>Configure replication on the slave node:<\/p>\n<p>file { &#8216;\/root\/.ldap_replication.ldif&#8217;:<br \/>\nensure =&gt; file,<br \/>\nsource =&gt; &#8216;puppet:\/\/\/homelab_files\/ldap_replication.ldif&#8217;,<br \/>\nowner =&gt; &#8216;0&#8217;,<br \/>\ngroup =&gt; &#8216;0&#8217;,<br \/>\nmode =&gt; &#8216;0600&#8217;,<br \/>\nnotify =&gt; Exec[&#8216;configure_replication&#8217;],<br \/>\n}<br \/>\nexec { &#8216;configure_replication&#8217;:<br \/>\ncommand =&gt; &#8216;ldapadd -c -Y EXTERNAL -H ldapi:\/\/\/ -f \/root\/.ldap_replication.ldif &amp;&amp; touch \/root\/.ldap_replication.done &amp;&amp; systemctl restart slapd&#8217;,<br \/>\npath =&gt; &#8216;\/usr\/bin:\/usr\/sbin:\/bin:\/sbin&#8217;,<br \/>\nprovider =&gt; shell,<br \/>\nonlyif =&gt; [&#8216;test -f \/root\/.ldap_config.done&#8217;],<br \/>\nunless =&gt; [&#8216;test -f \/root\/.ldap_replication.done&#8217;],<br \/>\n}<\/p>\n<p>Content of the file ldap_replication.ldif for the slave server is below. Note how we bind to the SSL port.<\/p>\n<p>dn: olcDatabase=hdb,cn=config<br \/>\nchangetype: modify<br \/>\nadd: olcSyncRepl<br \/>\nolcSyncRepl: rid=001<br \/>\nprovider=ldaps:\/\/ldap1.hl.local:636\/<br \/>\nsearchbase=&#8221;dc=hl.local,dc=top&#8221;<br \/>\ntype=refreshAndPersist<br \/>\nretry=&#8221;60 10 300 +&#8221;<br \/>\nschemachecking=on<br \/>\nbindmethod=simple<br \/>\nbinddn=&#8221;cn=reader,dc=top&#8221;<br \/>\ncredentials=PleaseChangeMe<br \/>\ntls_reqcert=never<br \/>\ntls_cert=\/etc\/pki\/tls\/certs\/hl.crt<br \/>\ntls_cacert=\/etc\/pki\/tls\/certs\/hl.crt<br \/>\ntls_key=\/etc\/pki\/tls\/private\/hl.pem<\/p>\n<h3>The Result<\/h3>\n<p>We should end up with the following LDAP structure:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lisenet.com\/wp-content\/uploads\/2018\/04\/lisenet-homelab-ldap-tree.png\" alt=\"\" width=\"161\" height=\"138\" \/><br \/>\nAnything that gets created on the LDAP master should be automatically synced to the slave.<\/p>\n<h3>Debugging LDAP Issues<\/h3>\n<p>If you hit problems, try running the following to start the LDAP server in debug mode with logging to the console:<\/p>\n<p># slapd -h ldapi:\/\/\/ -u ldap -d 255<\/p>\n<p>The logs can be a difficult to parse, but with Google search and a bit of luck you should to be able to work out what is going on.<\/p>\n<h2>Configure All Homelab Servers to use LDAP Authentication<\/h2>\n<p>We use Puppet module <a href=\"https:\/\/forge.puppet.com\/sgnl05\/sssd\" target=\"_blank\" rel=\"noopener\">sgnl05-sssd<\/a> to configure SSSD.<\/p>\n<p>Add the following to the main homelab environment manifest file \/etc\/puppetlabs\/code\/environments\/homelab\/manifests\/site.pp so that it gets applied to all servers.<\/p>\n<p>Note how SSSD is configured to use both LDAP servers for redundancy.<\/p>\n<p>class {&#8216;::sssd&#8217;:<br \/>\nensure =&gt; &#8216;present&#8217;,<br \/>\nconfig =&gt; {<br \/>\n&#8216;sssd&#8217; =&gt; {<br \/>\n&#8216;domains&#8217; =&gt; &#8216;default&#8217;,<br \/>\n&#8216;config_file_version&#8217; =&gt; 2,<br \/>\n&#8216;services&#8217; =&gt; [&#8216;nss&#8217;, &#8216;pam&#8217;],<br \/>\n},<br \/>\n&#8216;domain\/default&#8217; =&gt; {<br \/>\n&#8216;id_provider&#8217; =&gt; &#8216;ldap&#8217;,<br \/>\n&#8216;auth_provider&#8217; =&gt; &#8216;ldap&#8217;,<br \/>\n&#8216;cache_credentials&#8217; =&gt; true,<br \/>\n&#8216;default_shell&#8217; =&gt; &#8216;\/bin\/bash&#8217;,<br \/>\n&#8216;mkhomedir&#8217; =&gt; true,<br \/>\n&#8216;ldap_search_base&#8217; =&gt; &#8216;dc=hl.local,dc=top&#8217;,<br \/>\n&#8216;ldap_uri&#8217; =&gt; &#8216;ldaps:\/\/ldap1.hl.local,ldaps:\/\/ldap2.hl.local&#8217;,<br \/>\n&#8216;ldap_id_use_start_tls&#8217; =&gt; false,<br \/>\n&#8216;ldap_tls_reqcert&#8217; =&gt; &#8216;never&#8217;,<br \/>\n&#8216;ldap_default_bind_dn&#8217; =&gt; &#8216;cn=reader,dc=top&#8217;,<br \/>\n&#8216;ldap_default_authtok&#8217; =&gt; &#8216;PleaseChangeMe&#8217;,<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>After Puppet applies the configuration above, we should be able to log into all homelab servers with the LDAP user.<\/p>\n<p><a href=\"https:\/\/www.lisenet.com\/2018\/configure-openldap-master-slave-replication-with-puppet\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We\u2019re going to use Puppet to configure a pair of OpenLDAP servers with a master-slave replication. This article is part of the Homelab Project with KVM, Katello and Puppet series. Homelab We have two CentOS 7 servers installed which we want to configure as follows: ldap1.hl.local (10.11.1.11) \u2013 will be configured as an LDAP master &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.appservgrid.com\/paw92\/index.php\/2018\/10\/18\/configure-openldap-master-slave-replication-with-puppet-lisenet-com-linux-security\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Configure OpenLDAP Master\/Slave Replication with Puppet | Lisenet.com :: Linux | Security&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-693","post","type-post","status-publish","format-standard","hentry","category-linux"],"_links":{"self":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/693","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/comments?post=693"}],"version-history":[{"count":1,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/693\/revisions"}],"predecessor-version":[{"id":822,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/693\/revisions\/822"}],"wp:attachment":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/media?parent=693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/categories?post=693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/tags?post=693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}