How to initialize OpenLDAP 2.4.x server with OLC on CentOS 7

1. Install required packages

The first step is to install the OpenLDAP software packages.

# yum install openldap-servers openldap-clients

2. Copy default DB_CONFIG

OpenLDAP typically defaults to using one of two varieties of the Berkeley DB storage  format.  The standard Berkeley DB format is indicated by “bdb”.  A more recent version tuned for hierarchical databases like LDAP is known as “hdb”. CentOS/RHEL automatically creates an initial database with the hdb format.

The BDB derivatives are very tunable to a level  to which most people will not be interested.  The tuning is set in a file called DB_CONFIG which resides in the same directory as the database files (/var/lib/ldap). CentOS/RHEL offers a default tuning file and I generally use it unchanged which is located at:

/usr/share/openldap-servers/DB_CONFIG.example

First step is to copy this default file to the production directory:

# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG

At this point you can start and enable de slapd service:

# systemctl start slapd
# systemctl enable slapd

3. Loading the standarnd schemas

An LDAP service is a database in one traditional sense.  Each of the data objects is defined in a schema which describes the attributes of the object.    The schema must be loaded into the configuration database before the objects they define can be used in the user database.

The standard schema are provided as LDIF files which can be loaded using the ldapadd command.  The  call is similar to the ldapsearch command above:

# ldapadd -Q -Y -H ldapi:/// -f filename;

One CentOS/RHEL systems, the stock schema files are located in /etc/openldap/schema. Each one is offered in both the original LDAP schema form and in LDIF. Most LDAP databases will use three standard schema to start:

  • core
  • cosine
  • inetorgperson

These three define the basic objects and attributes needed to describe a typical organization: people, groups, rooms etc. Loading these three would look like this.

# ldapadd -Q -Y -H ldapi:/// -f /etc/openldap/schema/core.ldif
# ldapadd -Q -Y -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
# ldapadd -Q -Y -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif

4. Set the Database Suffix

Let’s say our company’s DN is:

dc=example,dc=local

Changes made using ldapadd or ldapmodify are defined using LDIF in the same way that the output of ldapsearch is expressed in LDIF.  We have to craft a change query for the olcSuffix of olcDatabase={2}hdb,cn=config and replace the existing value with our new one. Here’s what that looks like:

# ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=local

EOF
modifying entry "olcDatabase={2}hdb,cn=config"

The ldapadd and ldapmodify commands expect a stream of LDIF on stdin unless an input file is indicated with the -f option. I provided the update stream as a shell HERE document indicated by the EOF markers.

5. Set the Root DN

Now that we’ve set the suffix for our database we need to update the DN of the user who will be able to make changes (who is not the root user on the LDAP server host).

User names in LDAP are Distinguished Names of objects stored within the database, the same as any other record. We might want to keep the (common) name “Manager” but we need to place it within the proper hierarchy for our database. Since our database is now dc=example,dc=local then the manager really must be cn=Manager,dc=example,dc=local. We’ll update that in the same way that we did the suffix.

# ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=example,dc=local

EOF

modifying entry "olcDatabase={2}hdb,cn=config"

6. Set the root password

The final step of the stock LDAP service set up is to create a database user password which can be used to make queries and changes without requiring the system root user to do it. The attribute for this password is olcRootPW. (it goes with the olcRootDN set above). If the RootPW is unset then the RootDN cannot log in. When you add this attribute, you are opening up access to the database a bit, but securing the system by allowing the DB admin to work without needing system root access.

The OpenLDAP service can store passwords in clear text (bad idea) or using one of several one-way hash algorithms. You can create a new password hash using the slappasswd command. The default hash is currently SHA1, which is better than all of the others but still not 100% secure.

# slappasswd
New password: 
Re-enter new password: 
{SSHA}hashstringgenerated

The generated hash string will be placed as the value of the olcRootPW attribute.

# 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"

7. Create the top object in the database

Most organizations use their domain name as the pattern for the top DN and use an LDAP “organization” object for that top object. An organization object is a container. It is meant to have children of arbitrary types. This allows for the creation of any desired structure for the database. Because the suffix is a domain name, The object must also be a Domain Component object. Domain Components are not top level or container objects. They must have a parent. By combining the organization and domain component classes we create a top level object that can have the name we want.

Organization objects have only one required attribute. the o value is a string which is the organization’s name. It may also have a description attribute.

# ldapadd -x -w secret -D cn=Manager,dc=example,dc=local -H ldapi:/// <<EOF
dn: dc=example,dc=local
objectClass: dcObject
objectClass: organization
dc: example
o: example
structuralObjectClass: organization

EOF

How to fix “ldif_read_file: checksum error”

Well, in spite of you did read a banner saying “# AUTO-GENERATED FILE – DO NOT EDIT!! Use ldapmodify.” you ignored it and made some manual modifications in any of the LDIF files in /etc/ldap/slapd.d/.

Don’t worry it happened to me too :) When you need to quickly setup an openLDAP server for development it is pretty much easier to tweak these files although the recommended way is to use ldapmodify tool. But if you change the LDIF files in cn=config manually, their contents and checksums won’t match, which is not fatal, but is annoying when using tools such as slapcat:

544f7291 ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={1}monitor.ldif"
544f7291 ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif"

To fix it you have to recalculate their checksums, please follow the following steps:

1. Copy the errant file to an temporary directory (for example olcDatabase={2}hdb.ldif).

# cp /etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif /tmp

2. Remove the first two lines of that file where it is included the old checksum value

# tail -n +3 /tmp/olcDatabase={2}hdb.ldif &gt; fixed.ldif

3. Download the Check CRC tool from http://freecode.com/projects/checkcrc/

4. Extract the downloaded file

# tar xvfz check-4.3-src.tgz

5. Install the zlib development RPM package (or use APT on Debian based systems)

# yum install zlib-dev

6. Compile the check CRC tool:

# cd check-4.3
check4-3# gcc -O3 -Wall -DUSE_ZLIB -I/usr/include -o check check.c -L/usr/lib64 -lz

7. Calculate the new checksum

check-4.3# ./check /tmp/fixed.ldif
fixed.ldif        CRC-32 = 61e6182a, size = 582 bytes

8. Replace the new CRC-32 value into the original file using your favourite editor

# vi /etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif
AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
CRC32 61e6182a

 

Ansible mysql_secure_installation playbook

Right after installing MySQL/MariaDB server it is mandatory to run mysql_secure_installation tool that comes with the default server installation. This tool mainly removes the test database, test and anonymous users and set a new password for user root.

Following is an Ansible playbook to achieve the same results:

---
# Ansible mysql_secure_installation playbook

- name: delete anonymous MySQL server user for {{ ansible_hostname }}
  action: mysql_user user="" host="{{ ansible_hostname }}" state="absent"

- name: delete anonymous MySQL server user for localhost
  action: mysql_user user="" state="absent"

- name: remove the MySQL test database
  action: mysql_db db=test state=absent
  
  
# 'localhost' needs to be the last item for idempotency, see
# http://ansible.cc/docs/modules.html#mysql-user   
- name: Change root user password on first run
  mysql_user: login_user=root
              login_password=''
              name=root
              password={{ mysql_root_password }}
              priv=*.*:ALL,GRANT
              host={{ item }}
  with_items:
    - "{{ ansible_hostname }}"
    - 127.0.0.1
    - ::1
    - localhost

As it is not very recommended to store the MySQL root password anywhere, you will have to pass it as an Ansible variable:

$ ansible-playbook -i <your inventary> mysql_secure_installation.yml --extra-vars "mysql_root_password=<your password>"

How to fix SSH “Host key verification failed” error

If you’ve ever rebuilt a server that you have connected to in the past, chances are you’ve received an error when trying to ssh back into it for the first time since the rebuild. If you’re getting a screen that says “WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!”:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that the RSA host key has just been changed. The fingerprint for the RSA key sent by the remote host is b7:f5:48:4c:d0:1d:76:6a:50:4a:88:12:c7:80:f1:e5. Please contact your system administrator. Add correct host key in /home/user/.ssh/known_hosts to get rid of this message. Offending key in /home/user/.ssh/known_hosts:2 RSA host key for myhost has changed and you have requested strict checking. Host key verification failed. - See more at: http://injustfiveminutes.com/2014/08/13/how-to-fix-ssh-host-key-verification-failed-error

Since we just rebuilt our server, this error is expected as the it is sending a new RSA key different than the one stored in /home/user/.ssh/known_hosts and now your computer’s ssh system is saying, “Hold on, this server you’re connecting to via this IP is not giving me the same ID. It could be that you just rebuilt the server, or it could be a man-in-the-middle attack!”

The workaround is actually quite simple, we have to remove the stored RSA key so we can add safely the new one.
To do so, take a look at the last integer of the line that says “Offending ECDSA key,” because this integer is actually the line number inside your known_hosts file that’s throwing the error.

/home/user/.ssh/known_hosts:2 

Then type in the following command, changing the number 2 to whatever matches your own error.

sed -i '2d' ~/.ssh/known_hosts

 

UPDATED

The offending RSA key can be also be removed with:

ssh-keygen -f "/home/user/.ssh/known_hosts" -R <server ip>

ifconfig command not found on CentOS 7

CentOS 7 has been recently released studded with many new features. On the part of exploring the CentOS 7, you might encounter with its first change if you use the minimal installation.

On CentOS 6.x and before, ifconfig command by default used to shipped. Whereas in minimal installed CentOS 7 , ifconfig command it is not found.

To get the ifconfig command into our system , run the below given command as root:

yum install net-tools

What’s my public IP address from linux command line

Lots of times you need to determine your public IP address, if you are using Linux operating system to power your PC, you may use some good console commands to guess your public IP address.

Most of these methods will return you the local IP and not the public IP of your proxy if you are behind one.

WGET

wget -q -O - checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//'

CURL

curl -s checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//'

LYNX

lynx -dump ifconfig.me | grep 'IP Address'