Day 08: Infrastructure Access Blueprint: Jenkins & OpenLDAP
Infrastructure Access Blueprint: Jenkins & OpenLDAP
This file details the structural architecture, data schema, and operational boundaries of the local engineering identity ecosystem.
1. Network Topology
Both core services run containerized inside Docker Desktop and bridge their application footprints over a dedicated software overlay network.
- Docker Network Name:
jenkins-ldap-net - Internal Resolution Targets:
- Jenkins Server Endpoint:
http://jenkins-server:8080 - Directory Engine Service Socket:
ldap://ldap-server:389
- Jenkins Server Endpoint:
2. Directory Information Tree (DIT) Structure
The directory data layout uses a top-down tree schema to segregate accounts from transactional application groups.
dc=mycompany,dc=com (Root Context Base Domain)
├── uid=admin (Master Server Administrative Bind Identity)
│
├── ou=Users (Structural Namespace Container for Person Profiles)
│ ├── uid=alice.smith (Admin Profile Role mapping)
│ ├── uid=bob.jones (Admin Profile Role mapping)
│ ├── uid=charlie.brown (Developer Profile Role mapping)
│ └── uid=dana.white (Developer Profile Role mapping)
│
└── ou=Groups (Structural Namespace Container for Role Assignment Profiles)
├── cn=jenkins-admins (References admin profiles via explicit 'member' pointers)
└── cn=jenkins-developers (References engineering profiles via explicit 'member' pointers)
3. Account Profiles Ledger
Common Name (cn) |
User ID (uid) |
Corporate Email (mail) |
Password String | Assigned Access Profile Group |
|---|---|---|---|---|
| Alice Smith | alice.smith |
alice.smith@mycompany.com |
Password123456 |
jenkins-admins |
| Bob Jones | bob.jones |
bob.jones@mycompany.com |
Password123456 |
jenkins-admins |
| Charlie Brown | charlie.brown |
charlie.brown@mycompany.com |
Password123456 |
jenkins-developers |
| Dana White | dana.white |
dana.white@mycompany.com |
Password123456 |
jenkins-developers |
4. Production Jenkins Config Settings Reference
These exact string parameters map user login tokens securely back against the OpenLDAP context tree.
Core Security Realm Settings
- Server:
ldap://ldap-server:389 - root DN:
dc=mycompany,dc=com - User search base:
ou=Users - User search filter:
uid={0} - Manager DN:
uid=admin,dc=mycompany,dc=com
Group Mapping Specifications
- Group search base:
ou=Groups - Group search filter:
(&(objectClass=groupOfNames)(cn={0})) - Group Strategy selection: Check only
Search for LDAP groups containing user
Advanced Attribute Configurations
- Display Name LDAP attribute:
cn - Email Address LDAP attribute:
mail
5. Matrix-Based Security Permissions Layout
Group: jenkins-admins
- Assigned Rights: Global System Root Control (
Administer) - Privilege Level: Can manage plugins, override system configuration nodes, adjust credentials pipelines, and spin up structural worker nodes.
Group: jenkins-developers
- Assigned Rights: Operational Application Execution Boundaries
- Permitted Grid Checkboxes:
Overall / ReadDashboard / ReadJob / Build,Job / Cancel,Job / Read,Job / WorkspaceRun / Replay,Run / UpdateView / Read
- Privilege Level: Restricted to application code deployment pipelines. System configuration submenus are safely hidden from these users.
Infrastructure Access Blueprint: Jenkins & OpenLDAP
This document details the configuration, structural layout, and access patterns established for the local containerized identity ecosystem.
1. Infrastructure Deployment (Docker Setup)
- Jenkins Container: Running via
jenkins/jenkins:ltson port8080[1]. Data is safely persisted on your Mac host via a Docker volume (jenkins_home) [1]. - OpenLDAP Container: Running via
vegardit/openldapon port389. Data is bound directly to your local workspace (/ldap_dataand/ldap_config) for easier local development access on macOS. - Container Networking: Both containers are securely bridged together via a custom Docker virtual bridge network named
jenkins-ldap-net, enabling them to communicate directly using container names as internal domain addresses.
2. Directory Tree Layout (LDAP Hierarchy)
The directory database is structured dynamically using standard LDAP object identifiers:
dc=mycompany,dc=com (Root Domain)
├── uid=admin (Master Directory Manager Account)
│
├── ou=Users (Structural Organizational Unit)
│ ├── uid=alice.smith (Pass: Password123456 | cn: Alice Smith | Group: admins)
│ ├── uid=bob.jones (Pass: Password123456 | cn: Bob Jones | Group: admins)
│ ├── uid=charlie.brown (Pass: Password123456 | cn: Charlie Brown | Group: developers)
│ └── uid=dana.white (Pass: Password123456 | cn: Dana White | Group: developers)
│
└── ou=Groups (Structural Organizational Unit)
├── cn=jenkins-admins (Explicit Member Pointer: alice.smith, bob.jones)
└── cn=jenkins-developers (Explicit Member Pointer: charlie.brown, dana.white)
3. Key Integration Resolutions
During development, we resolved several authentication and layout blocks:
- Data Injection Intermission: Solved an issue where user records were initially missing (
numResponses: 1) by manually forcing the LDIF injection after the server finalized its background boot sequence. - Lookup & Parameter Matching: Configured Jenkins to use the custom user filter
uid={0}and mapped the missingdisplayNamelogic directly to the native common name (cn) attribute. - Email Attribute Patch: Fixed profile schema validation warnings by executing an
ldapmodifyinjection script to add corporatemailattributes (e.g.,alice.smith@mycompany.com) to all active users. - Group Mapping Calibration: Fixed group assignment failures by disabling the user-attribute
memberOfcheckbox Strategy and forcing Jenkins to use the container search filter(&(objectClass=groupOfNames)(cn={0})).
4. Active Access Control Profile
You are utilizing Matrix-based security to divide infrastructure duties according to standard enterprise guidelines:
jenkins-adminsRow: Assigned fullAdministerroot privileges. Users likealice.smithretain deep system, plugin, and hardware-node management control.jenkins-developersRow: Assigned limited operations access (Overall/Read,Job/Build,Job/Workspace). Users likecharlie.browncan execute and troubleshoot engineering pipeline builds, but system-wide settings pages are hidden from view.
#!/bin/bash
# 1. Define Local Paths for Persistence (macOS Bind Mounts)
DATA_DIR="$(pwd)/ldap_data"
CONF_DIR="$(pwd)/ldap_config"
NETWORK_NAME="jenkins-ldap-net"
echo "=========================================================="
echo " Starting OpenLDAP Development Environment Deployment"
echo "=========================================================="
# 2. Setup Network Topology
if ! docker network inspect "$NETWORK_NAME" >/dev/null 2>&1; then
echo "Creating custom bridge network: $NETWORK_NAME..."
docker network create "$NETWORK_NAME"
else
echo "Bridge network $NETWORK_NAME already exists."
fi
# 3. Cleanup old deployment blocks
echo "Cleaning up stale container instances and local mount directories..."
docker rm -f ldap-server 2>/dev/null
sudo rm -rf "$DATA_DIR" "$CONF_DIR"
# Create clean host volumes
mkdir -p "$DATA_DIR" "$CONF_DIR"
# 4. Start the Server Container attached to the custom network
echo "Launching OpenLDAP Engine container..."
docker run -d \
-p 389:389 \
--name ldap-server \
--network "$NETWORK_NAME" \
--restart on-failure \
-e LDAP_INIT_ORG_DN='dc=mycompany,dc=com' \
-e LDAP_INIT_ROOT_USER_DN='uid=admin,dc=mycompany,dc=com' \
-e LDAP_INIT_ROOT_USER_PW='newpassword123' \
-e LDAP_INIT_ORG_NAME='MyCompany Corp' \
-e LDAP_INIT_PPOLICY_PW_MIN_LENGTH='12' \
-v "$DATA_DIR":/var/lib/ldap \
-v "$CONF_DIR":/etc/ldap/slapd.d \
vegardit/openldap:latest
# 5. Dynamic Health Check Loop (Replaces unreliable blind sleeps)
echo "Waiting for LDAP directory service socket to initialize..."
MAX_ATTEMPTS=30
ATTEMPT=1
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
if docker exec ldap-server ldapsearch -x -H ldap://localhost:389 -b "dc=mycompany,dc=com" >/dev/null 2>&1; then
echo "LDAP Service engine is live and responding to internal queries!"
break
fi
echo "Database initialization in progress... (Attempt $ATTEMPT/$MAX_ATTEMPTS)"
sleep 2
ATTEMPT=$((ATTEMPT + 1))
done
if [ $ATTEMPT -gt $MAX_ATTEMPTS ]; then
echo "ERROR: OpenLDAP container timed out during initialization. Terminating."
exit 1
fi
# 6. Inject Full Structure, Users with Mail, and Groups
echo "Injecting operational organizational units, user records, and role matrices..."
docker exec -i ldap-server bash -c 'cat <<EOF > /tmp/data.ldif
dn: ou=Users,dc=mycompany,dc=com
objectClass: organizationalUnit
ou: Users
dn: ou=Groups,dc=mycompany,dc=com
objectClass: organizationalUnit
ou: Groups
dn: uid=alice.smith,ou=Users,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: alice.smith
cn: Alice Smith
sn: Smith
mail: alice.smith@mycompany.com
userPassword: Password123456
dn: uid=bob.jones,ou=Users,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: bob.jones
cn: Bob Jones
sn: Jones
mail: bob.jones@mycompany.com
userPassword: Password123456
dn: uid=charlie.brown,ou=Users,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: charlie.brown
cn: Charlie Brown
sn: Brown
mail: charlie.brown@mycompany.com
userPassword: Password123456
dn: uid=dana.white,ou=Users,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: dana.white
cn: Dana White
sn: White
mail: dana.white@mycompany.com
userPassword: Password123456
dn: cn=jenkins-admins,ou=Groups,dc=mycompany,dc=com
objectClass: groupOfNames
cn: jenkins-admins
member: uid=alice.smith,ou=Users,dc=mycompany,dc=com
member: uid=bob.jones,ou=Users,dc=mycompany,dc=com
dn: cn=jenkins-developers,ou=Groups,dc=mycompany,dc=com
objectClass: groupOfNames
cn: jenkins-developers
member: uid=charlie.brown,ou=Users,dc=mycompany,dc=com
member: uid=dana.white,ou=Users,dc=mycompany,dc=com
EOF
ldapadd -x -D "uid=admin,dc=mycompany,dc=com" -w newpassword123 -f /tmp/data.ldif'
# 7. Hot-connect existing Jenkins container if present
if docker ps -a --format '' | grep -q "^jenkins-server$"; then
echo "Connecting active 'jenkins-server' instance to network topology..."
docker network connect "$NETWORK_NAME" jenkins-server 2>/dev/null || true
fi
echo "--------------------------------------------------------"
echo " Configuration Complete! Environment Is Fully Operational"
echo " Base Target Path DN : dc=mycompany,dc=com"
echo " Bind Manager Account: uid=admin,dc=mycompany,dc=com"
echo "--------------------------------------------------------"