Series: Centralized DB Authentication in the Wild | Part 2 of 9
Introduction
In Part 1, we looked at why local database authentication becomes difficult to manage as environments grow. Every database maintains its own users, passwords and roles, making onboarding, offboarding and access changes repetitive across multiple systems.
- We'll deploy OpenLDAP using Docker, create an enterprise-style directory with users, service accounts and groups, and verify that the directory is ready for database integration. The same identity platform will be reused throughout the rest of this series.
- Before connecting any database to a centralized authentication platform, we first need a directory service that every database can trust. That is what this article builds.
Note
- This demo environment runs on a dedicated Linux host: iam.dbacraft.com OpenLDAP and phpLDAPadmin both run in Docker on this host.
- Always test in a non-production environment before deploying identity infrastructure changes to a live system.
Demo environment
| Component | Host | Detail |
|---|---|---|
| OpenLDAP | iam.dbacraft.com | osixia/openldap:1.5.0, port 389 |
| phpLDAPadmin | iam.dbacraft.com | osixia/phpldapadmin:0.9.0, port 8081 |
| Base DN | iam.dbacraft.com | dc=dbacraft,dc=com |
| Database hosts | db1.dbacraft.com | PostgreSQL, MongoDB, MySQL, MariaDB |
Step 1: Deploy OpenLDAP and phpLDAPadmin
OpenLDAP provides the centralized directory service used throughout this series. phpLDAPadmin provides a web interface for browsing and managing the directory.
Deploy both services using the following Docker Compose file.
# Path: /opt/auth/ldap/docker-compose.yml # Run on: iam.dbacraft.com version: "3.8" services: openldap: image: osixia/openldap:1.5.0 container_name: dbacraft_openldap_389 hostname: iam.dbacraft.com restart: unless-stopped environment: LDAP_ORGANISATION: "DBACraft Auth" LDAP_DOMAIN: "dbacraft.com" LDAP_BASE_DN: "dc=dbacraft,dc=com" LDAP_ADMIN_PASSWORD: "********" LDAP_CONFIG_PASSWORD: "********" LDAP_TLS: "false" ports: - "389:389" - "636:636" volumes: - ldap_data:/var/lib/ldap - ldap_config:/etc/ldap/slapd.d phpldapadmin: image: osixia/phpldapadmin:0.9.0 container_name: dbacraft_phpldapadmin_8081 restart: unless-stopped environment: PHPLDAPADMIN_LDAP_HOSTS: "openldap" PHPLDAPADMIN_HTTPS: "false" ports: - "8081:80" depends_on: - openldap volumes: ldap_data: ldap_config:
Start both containers.
root@iam:/opt/auth/ldap# docker compose up -d
Verify both containers are running.
root@iam:/opt/auth/ldap# docker ps
phpLDAPadmin is accessible at http://iam.dbacraft.com:8081
Step 2: Build the directory structure
An LDAP directory is organized as a hierarchical tree. The root of the directory is the Base DN and every object exists beneath it.
For this article, the directory starts with dc=dbacraft,dc=com and contains two organizational units.
ou=peoplestores user accounts and service accounts.ou=groupsstores authorization groups.
dc=dbacraft,dc=com
│
├── ou=people ← all users and service accounts
└── ou=groups ← all authorization groups
Create both organizational units using LDIF files with ldapadd or through the phpLDAPadmin web interface. Both methods produce the same directory structure.
Step 3: User naming convention
A consistent naming convention makes identities easier to manage, automate and audit. As the directory grows, predictable names simplify administration and reduce the chance of configuration mistakes.
For this article, every identity follows a standard naming pattern based on its role.
| Identity type | Naming pattern | Examples |
|---|---|---|
| DBA users | user_[name]_dba | user_ahmad_dba, user_siti_dba, user_wei_dba |
| System administrators | user_[name]_sysadmin | user_farah_sysadmin, user_kumar_sysadmin |
| Developers | user_[name]_dev | user_arif_dev, user_mei_dev, user_daniel_dev |
| BI users | user_[name]_bi | user_zainab_bi, user_chong_bi, user_faiz_bi |
| Service accounts (read-only) | svc_[system]_ro | svc_billing_ro, svc_analytics_ro, svc_orders_ro |
| Service accounts (read-write) | svc_[system]_rw | svc_inventory_rw, svc_search_rw |
| Bind account | svc_ldap_bind_ro | Read-only account used by applications to search the directory |
The _ro and _rw suffixes indicate the intended access level of a service account. Using descriptive names makes it easier to identify an account's purpose during routine administration, troubleshooting and security reviews.
The svc_ldap_bind_ro account is a dedicated read-only service account used by applications to search the directory during authentication. It has no administrative privileges and is separate from the LDAP administrator account. We'll use this account when integrating with database services.
Step 4: Create the users
The directory contains user accounts for database administrators, developers, system administrators, BI users and service accounts. Each user is created as an LDAP entry under ou=people using an LDIF file.
The example below shows the structure of a typical user account.
# Example: DBA user entry dn: uid=user_ahmad_dba,ou=people,dc=dbacraft,dc=com objectClass: inetOrgPerson uid: user_ahmad_dba cn: Ahmad sn: DBA mail: ahmad@dbacraft.com userPassword: ********
Create the user entries using LDIF files and import them with ldapadd.
In addition to user accounts, the directory includes a dedicated read-only service account used by applications to search the directory during authentication.
# Dedicated read-only bind account for database platform integration dn: uid=svc_ldap_bind_ro,ou=people,dc=dbacraft,dc=com objectClass: inetOrgPerson uid: svc_ldap_bind_ro cn: LDAP Bind Service sn: BindRO mail: svc-ldap-bind@dbacraft.com userPassword: ********
Step 5: Create the groups
Groups are used to organize users based on their responsibilities. Instead of managing permissions for individual accounts, users become members of one or more groups that represent their role within the organization.
For this article, we'll create the following groups.
| Group CN | Purpose | Members |
|---|---|---|
| cn=db-admins | Database administrators | 6 DBA users |
| cn=server-admins | Linux and infrastructure administrators | 5 sysadmin users |
| cn=developers | Application developers | 5 developer users |
| cn=bi-users | Reporting and analytics users | 5 BI users |
| cn=service-accounts | Application and automation service accounts | 10 service accounts |
Managing access through groups simplifies administration. When a user's responsibilities change, we can just update their group membership instead of managing individual accounts across multiple systems. As more databases are integrated into the directory, this group-based model scales far better than maintaining permissions for every user separately.
The following example shows the developers group.
dn: cn=developers,ou=groups,dc=dbacraft,dc=com
objectClass: groupOfNames
cn: developers
member: uid=user_arif_dev,ou=people,dc=dbacraft,dc=com
member: uid=user_mei_dev,ou=people,dc=dbacraft,dc=com
member: uid=user_daniel_dev,ou=people,dc=dbacraft,dc=com
member: uid=user_ravi_dev,ou=people,dc=dbacraft,dc=com
member: uid=user_lily_dev,ou=people,dc=dbacraft,dc=com
Step 6: Verify the directory
Use ldapsearch to verify that the directory has been created successfully. The output should include the organizational units, user accounts, service accounts and groups created in the previous steps.
root@iam:/opt/auth/ldap# ldapsearch -x -LLL \
-D "cn=admin,dc=dbacraft,dc=com" -W \
-b "dc=dbacraft,dc=com" dn
Example output:
dn: dc=dbacraft,dc=com
dn: ou=people,dc=dbacraft,dc=com
dn: ou=groups,dc=dbacraft,dc=com
dn: uid=user_ahmad_dba,ou=people,dc=dbacraft,dc=com
dn: uid=user_arif_dev,ou=people,dc=dbacraft,dc=com
dn: uid=user_zainab_bi,ou=people,dc=dbacraft,dc=com
dn: uid=svc_inventory_rw,ou=people,dc=dbacraft,dc=com
dn: uid=svc_ldap_bind_ro,ou=people,dc=dbacraft,dc=com
dn: cn=db-admins,ou=groups,dc=dbacraft,dc=com
dn: cn=developers,ou=groups,dc=dbacraft,dc=com
dn: cn=bi-users,ou=groups,dc=dbacraft,dc=com
dn: cn=server-admins,ou=groups,dc=dbacraft,dc=com
dn: cn=service-accounts,ou=groups,dc=dbacraft,dc=com
...
Production considerations
| Consideration | Detail |
|---|---|
| Transport security | This demo uses LDAP over port 389 for simplicity. In production, use LDAPS (636) or StartTLS to encrypt authentication traffic. |
| High availability | Avoid a single LDAP server in production. Deploy replicas so authentication remains available if one server fails. |
| Backups | Regularly back up the LDAP data and configuration. The directory becomes the central identity source for every connected database. |
| Bind account security | Create a dedicated read-only bind account with the minimum required permissions. Do not reuse the LDAP administrator account for application authentication. |
| Naming convention | Establish a consistent naming convention before creating users. Changing user IDs later can affect applications and database integrations that depend on them. |
Wrapping Up
- In this article, we deployed OpenLDAP and built a centralized enterprise directory using a structured hierarchy of users, service accounts and groups.
- The directory is now ready to become the central identity source for the environments used throughout the rest of this series. By establishing consistent naming standards and group-based organization from the start, future integrations become much easier to manage.
- From this point forward, we'll use the same directory as we integrate PostgreSQL, MongoDB, MySQL and MariaDB without rebuilding the identity infrastructure.
What is next
In Part 3, we'll integrate PostgreSQL with the directory created in this article. We'll configure LDAP authentication in pg_hba.conf, verify user authentication and examine how PostgreSQL handles authorization for LDAP-authenticated users.
References
Series: Centralized DB Authentication in the Wild
- Part 1: Why Local Database Authentication Creates Operational Chaos
- Part 2: Building an Enterprise LDAP Directory with OpenLDAP
- Part 3: Integrating PostgreSQL with a Centralized LDAP Directory (coming soon)
- Part 4: MongoDB Enterprise LDAP Integration (coming soon)
- Part 5: MySQL Enterprise LDAP Integration (coming soon)
- Part 6: MariaDB LDAP Authentication using PAM and POSIX Groups (coming soon)
- Part 7: Why LDAP Is Not Enough - Introducing Kerberos (coming soon)
- Part 8: Certificate-Based Authentication Across PostgreSQL, MySQL, MariaDB and MongoDB (coming soon)
- Part 9: Production Best Practices and Cross Platform Comparison (coming soon)

No comments:
Post a Comment