Working after iterations

This commit is contained in:
2025-10-16 15:43:24 -07:00
committed by Spencer Jones
parent 0bac69c801
commit 857c71484a
10 changed files with 778 additions and 39 deletions

6
.gitignore vendored
View File

@@ -86,9 +86,13 @@ logs/
*.bak
*.tmp
# Environment files with secrets
# Environment files
# Note: .env is tracked and contains non-secret configuration (ports, etc.)
# Add secrets only to .env.local which is ignored
.env.local
.env.*.local
.env.production
.env.development
# MacOS
.DS_Store

94
CHANGELOG.md Normal file
View File

@@ -0,0 +1,94 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.1.0] - 2025-01-XX
### Added
- Initial release of LDAP Docker development tool
- OpenLDAP 1.5.0 container with SSL/TLS support
- phpLDAPadmin web interface for easy administration
- Pre-configured test users and groups for testing.local domain
- SSL certificate generation script using Python cryptography
- Comprehensive CLI tool for managing LDAP server (`ldap-docker` command)
- Makefile with convenient shortcuts for common operations
- Interactive quickstart script (`quickstart.sh`) for guided setup
- Example Python authentication script demonstrating LDAP integration
- Support for custom dev-ca certificates
- Persistent Docker volumes for data and configuration
- Test suite for certificate generation
- Comprehensive documentation:
- README.md - Full project documentation
- GETTING_STARTED.md - Beginner-friendly guide
- QUICKREF.md - Quick command reference
- certs/README.md - Certificate management guide
- examples/README.md - Integration patterns and examples
### Test Data
- 4 pre-configured test users (admin, jdoe, jsmith, testuser)
- 3 test groups (admins, developers, users)
- All test users use password: `password123`
- Admin credentials: `cn=admin,dc=testing,dc=local` / `admin_password`
### Infrastructure
- Docker Compose configuration for easy deployment
- UV package manager integration for Python dependencies
- Cross-platform support (MacOS, Linux, Windows)
- Rancher Desktop and Docker Desktop compatibility
### Fixed
- Updated `pyproject.toml` to use `dependency-groups.dev` instead of deprecated `tool.uv.dev-dependencies`
- Added `tool.hatch.build.targets.wheel.packages` configuration to fix build errors
- Removed obsolete `version` field from `docker-compose.yml` (Docker Compose v2+ compatibility)
- Fixed LDAP user password hashes to use proper SSHA format generated by `slappasswd`
- Fixed attribute type conversion in example scripts for uidNumber and gidNumber
### Technical Details
- Base DN: `dc=testing,dc=local`
- LDAP Port: 389 (standard)
- LDAPS Port: 636 (SSL/TLS)
- Web Admin Port: 8080
- Python 3.9+ required
- Docker/Rancher Desktop required
## [Unreleased]
### Planned Features
- Additional integration examples (Node.js, Go, Ruby, etc.)
- Health check endpoints
- Automated backup scripts
- Docker image with pre-built configuration
- Kubernetes/Helm deployment examples
- LDAP replication setup guide
- Performance tuning guide
- Security hardening options
---
## Release Notes
### Version 0.1.0
This is the initial release providing a complete LDAP development environment suitable for:
- Testing LDAP authentication in applications
- Development and integration testing
- Learning LDAP concepts
- Prototyping LDAP-based systems
**Important Security Notes:**
- This tool is for **DEVELOPMENT USE ONLY**
- Default passwords are well-known and insecure
- Self-signed certificates are not suitable for production
- Never use this with real user data or in production environments
### Upgrade Instructions
Not applicable for initial release.
### Breaking Changes
Not applicable for initial release.
---
For support, issues, or feature requests, please refer to the project documentation or open an issue on the project repository.

View File

@@ -1,5 +1,11 @@
.PHONY: help install init start stop restart down logs status certs-generate certs-check test-connection test-auth test-users clean clean-all
# Load environment variables from .env file if it exists
ifneq (,$(wildcard ./.env))
include .env
export
endif
# Default target
.DEFAULT_GOAL := help
@@ -55,9 +61,9 @@ start: ## Start the LDAP server
@echo "✅ LDAP server started"
@echo ""
@echo "Services available at:"
@echo " - LDAP: ldap://localhost:389"
@echo " - LDAPS: ldaps://localhost:636"
@echo " - Admin: http://localhost:8080"
@echo " - LDAP: ldap://localhost:$${LDAP_PORT:-389}"
@echo " - LDAPS: ldaps://localhost:$${LDAPS_PORT:-636}"
@echo " - Admin: http://localhost:$${PHPLDAPADMIN_PORT:-8080}"
@echo ""
@echo "Admin credentials:"
@echo " DN: cn=admin,dc=testing,dc=local"
@@ -105,19 +111,19 @@ status: ## Show container status
test-connection: ## Test connection to LDAP server
@echo "Testing LDAP connection..."
uv run python -c "from ldap3 import Server, Connection, ALL; s = Server('ldap://localhost:389', get_info=ALL); c = Connection(s, auto_bind=True); print('✅ Connection successful'); c.unbind()"
@export LDAP_PORT=$${LDAP_PORT:-389}; uv run python -c "import os; from ldap3 import Server, Connection, ALL; s = Server(f\"ldap://localhost:{os.environ.get('LDAP_PORT', '389')}\", get_info=ALL); c = Connection(s, auto_bind=True); print('✅ Connection successful'); c.unbind()"
test-auth: ## Test authentication with admin user
@echo "Testing LDAP authentication..."
uv run python -c "from ldap3 import Server, Connection; s = Server('ldap://localhost:389'); c = Connection(s, 'cn=admin,dc=testing,dc=local', 'admin_password', auto_bind=True); print('✅ Authentication successful'); c.unbind()"
@export LDAP_PORT=$${LDAP_PORT:-389}; uv run python -c "import os; from ldap3 import Server, Connection; s = Server(f\"ldap://localhost:{os.environ.get('LDAP_PORT', '389')}\"); c = Connection(s, 'cn=admin,dc=testing,dc=local', 'admin_password', auto_bind=True); print('✅ Authentication successful'); c.unbind()"
test-users: ## List all users in LDAP
@echo "Listing LDAP users..."
@uv run python -c "from ldap3 import Server, Connection; s = Server('ldap://localhost:389'); c = Connection(s, 'cn=admin,dc=testing,dc=local', 'admin_password', auto_bind=True); c.search('dc=testing,dc=local', '(objectClass=inetOrgPerson)', attributes=['uid', 'cn', 'mail']); [print(f' - {e.cn}: {e.uid} ({e.mail})') for e in c.entries]; c.unbind()"
@export LDAP_PORT=$${LDAP_PORT:-389}; uv run python -c "import os; from ldap3 import Server, Connection; s = Server(f\"ldap://localhost:{os.environ.get('LDAP_PORT', '389')}\"); c = Connection(s, 'cn=admin,dc=testing,dc=local', 'admin_password', auto_bind=True); c.search('dc=testing,dc=local', '(objectClass=inetOrgPerson)', attributes=['uid', 'cn', 'mail']); [print(f' - {e.cn}: {e.uid} ({e.mail})') for e in c.entries]; c.unbind()"
test-ssl: ## Test SSL/TLS connection
@echo "Testing LDAPS connection..."
openssl s_client -connect localhost:636 -CAfile certs/ca.crt </dev/null
openssl s_client -connect localhost:$${LDAPS_PORT:-636} -CAfile certs/ca.crt </dev/null
test-all: test-connection test-auth test-users ## Run all tests
@@ -126,7 +132,7 @@ shell: ## Open a shell in the LDAP container
ldapsearch: ## Run ldapsearch command (example query)
@echo "Running ldapsearch..."
ldapsearch -H ldap://localhost:389 -x -b "dc=testing,dc=local" -D "cn=admin,dc=testing,dc=local" -w admin_password
ldapsearch -H ldap://localhost:$${LDAP_PORT:-389} -x -b "dc=testing,dc=local" -D "cn=admin,dc=testing,dc=local" -w admin_password
clean: ## Clean Python build artifacts
@echo "Cleaning build artifacts..."

436
PORT_CONFIGURATION.md Normal file
View File

@@ -0,0 +1,436 @@
# Port Configuration Guide
This guide explains how to configure custom ports for your LDAP Docker environment to avoid conflicts with other services.
## Quick Start
**To change ports, simply edit the `.env` file:**
```bash
# Edit .env file
LDAP_PORT=20389
LDAPS_PORT=20636
PHPLDAPADMIN_PORT=8080
```
Then restart:
```bash
make down && make start
```
That's it! All scripts and tools will automatically use your custom ports.
---
## Why Custom Ports?
You might want to use custom ports if:
- You have another LDAP server running on standard ports (389/636)
- Port 389 requires root/admin privileges
- You're running multiple LDAP environments simultaneously
- Your organization has specific port requirements
## Files Involved
The port configuration system uses these files:
### 1. `.env` - Your Configuration (Edit This!)
```bash
LDAP_PORT=20389 # Your custom LDAP port
LDAPS_PORT=20636 # Your custom LDAPS port
PHPLDAPADMIN_PORT=8080 # Web admin interface port
```
### 2. `docker-compose.yml` - Uses Environment Variables
```yaml
ports:
- "${LDAP_PORT:-389}:389" # Host:Container mapping
- "${LDAPS_PORT:-636}:636"
```
The `${LDAP_PORT:-389}` syntax means:
- Use `$LDAP_PORT` if set in `.env`
- Otherwise use default `389`
### 3. Scripts - Auto-detect Ports
All Python scripts and Makefile commands read from `.env` automatically:
- `scripts/cli.py`
- `scripts/ldapsearch_helper.sh`
- `examples/simple_auth.py`
- `Makefile`
## How to Change Ports
### Method 1: Edit .env File (Recommended)
1. **Edit `.env`:**
```bash
vim .env # or your favorite editor
```
2. **Change the port values:**
```bash
LDAP_PORT=20389
LDAPS_PORT=20636
```
3. **Restart the containers:**
```bash
make down && make start
```
4. **Verify:**
```bash
docker-compose ps
# Should show 0.0.0.0:20389->389/tcp
```
### Method 2: Environment Variables (Temporary)
For one-time use without modifying `.env`:
```bash
LDAP_PORT=30389 LDAPS_PORT=30636 docker-compose up -d
```
### Method 3: Create .env.local (Advanced)
For personal overrides without modifying the main `.env`:
```bash
# Create .env.local (git-ignored)
echo "LDAP_PORT=12389" > .env.local
echo "LDAPS_PORT=12636" >> .env.local
# Docker Compose will merge both files
docker-compose up -d
```
## Testing with Custom Ports
### Automatic - Use Our Tools
All our tools automatically detect your ports from `.env`:
```bash
# These all work automatically with your custom ports
make test-users
make test-connection
uv run python examples/simple_auth.py
```
### Generate ldapsearch Commands
Use our helper script to generate commands with your ports:
```bash
./scripts/ldapsearch_helper.sh
```
Output includes commands like:
```bash
# List all users
ldapsearch -H ldap://localhost:20389 \
-D "cn=admin,dc=testing,dc=local" \
-w admin_password \
-b "ou=people,dc=testing,dc=local" \
"(objectClass=inetOrgPerson)" \
uid cn mail
```
### Manual ldapsearch Commands
Replace `389` with your `LDAP_PORT` and `636` with your `LDAPS_PORT`:
```bash
# Standard LDAP (unencrypted)
ldapsearch -H ldap://localhost:20389 \
-D "cn=admin,dc=testing,dc=local" \
-w admin_password \
-b "dc=testing,dc=local"
# LDAPS (SSL/TLS)
ldapsearch -H ldaps://localhost:20636 \
-D "cn=admin,dc=testing,dc=local" \
-w admin_password \
-b "dc=testing,dc=local"
# Search for specific user
ldapsearch -H ldap://localhost:20389 \
-D "cn=admin,dc=testing,dc=local" \
-w admin_password \
-b "dc=testing,dc=local" \
"(uid=jdoe)"
# Test user authentication
ldapsearch -H ldap://localhost:20389 \
-D "uid=jdoe,ou=people,dc=testing,dc=local" \
-w password123 \
-b "dc=testing,dc=local" \
"(uid=jdoe)"
```
### Using Python
```python
import os
from ldap3 import Server, Connection
# Automatically uses LDAP_PORT from environment
port = os.environ.get('LDAP_PORT', '389')
server = Server(f'ldap://localhost:{port}')
conn = Connection(server,
user='cn=admin,dc=testing,dc=local',
password='admin_password',
auto_bind=True)
conn.search('dc=testing,dc=local', '(objectClass=*)')
print(f"Connected on port {port}")
conn.unbind()
```
## Common Port Configurations
### Development (Unprivileged Ports)
```bash
LDAP_PORT=20389
LDAPS_PORT=20636
PHPLDAPADMIN_PORT=8080
```
### Testing (High Ports)
```bash
LDAP_PORT=30389
LDAPS_PORT=30636
PHPLDAPADMIN_PORT=8090
```
### Multiple Environments
```bash
# Environment 1 (.env)
LDAP_PORT=20389
LDAPS_PORT=20636
# Environment 2 (separate directory or .env.local)
LDAP_PORT=21389
LDAPS_PORT=21636
```
## Troubleshooting
### Port Already in Use
**Error:** `Bind for 0.0.0.0:20389 failed: port is already allocated`
**Check what's using the port:**
```bash
lsof -i :20389
# or
netstat -an | grep 20389
```
**Solutions:**
1. Stop the conflicting service
2. Choose a different port in `.env`
3. Use `make down` to stop this LDAP server first
### Scripts Not Using Custom Ports
**Problem:** Scripts still connect to port 389
**Solution:** Ensure `.env` is loaded:
1. **Check .env exists:**
```bash
ls -la .env
```
2. **Verify ports are set:**
```bash
grep LDAP_PORT .env
```
3. **Reload environment:**
```bash
source .env # For bash scripts
make down && make start # Restart containers
```
### Docker Compose Not Reading .env
**Problem:** Containers still on default ports
**Check:**
```bash
# View what Docker Compose sees
docker-compose config | grep -A2 ports
```
**Solution:**
```bash
# Ensure .env is in project root
pwd # Should be ldap_docker/
ls .env # Should exist
# Force reload
docker-compose down
docker-compose up -d
```
### Can't Connect After Port Change
**Verify containers are running on correct ports:**
```bash
docker-compose ps
# Should show: 0.0.0.0:20389->389/tcp
```
**Test connectivity:**
```bash
# Test if port is listening
nc -zv localhost 20389
# Test LDAP response
ldapsearch -H ldap://localhost:20389 -x -b "" -s base
```
**Check logs:**
```bash
make logs
# Look for: "slapd starting"
```
## Port Reference Table
| Service | Default Port | Docker Internal Port | Configurable Via |
|---------|--------------|---------------------|------------------|
| LDAP | 389 | 389 | `LDAP_PORT` in .env |
| LDAPS | 636 | 636 | `LDAPS_PORT` in .env |
| phpLDAPadmin | 8080 | 80 | `PHPLDAPADMIN_PORT` in .env |
**Note:** The "Docker Internal Port" (right side of mapping) never changes. Only the host port (left side) is configurable.
## Advanced: Port Mapping Explained
Docker port mapping format: `HOST:CONTAINER`
```yaml
ports:
- "20389:389"
```
This means:
- **20389** = Port on your Mac (accessible via `localhost:20389`)
- **389** = Port inside the Docker container (LDAP's standard port)
The container always listens on 389 internally. We just map it to 20389 externally.
## Testing Multiple Configurations
Run multiple LDAP servers simultaneously:
```bash
# Terminal 1: First instance
cd ldap_docker_1
echo "LDAP_PORT=20389" > .env
echo "LDAPS_PORT=20636" >> .env
make start
# Terminal 2: Second instance
cd ldap_docker_2
echo "LDAP_PORT=21389" > .env
echo "LDAPS_PORT=21636" >> .env
make start
# Now you have two LDAP servers running!
ldapsearch -H ldap://localhost:20389 ... # Server 1
ldapsearch -H ldap://localhost:21389 ... # Server 2
```
## Best Practices
1. **Use .env for configuration** - Don't hardcode ports in scripts
2. **Document your ports** - Add comments in .env explaining your choices
3. **Use unprivileged ports** - Ports above 1024 don't require root
4. **Avoid common ports** - Skip 8080, 3000, 5000 (often used by other tools)
5. **Be consistent** - If LDAP is 20389, make LDAPS 20636 (same prefix)
## Integration Examples
### Configure Your Application
After changing ports, update your application's LDAP configuration:
```python
# Django settings.py
AUTH_LDAP_SERVER_URI = "ldap://localhost:20389"
# Flask
LDAP_HOST = "localhost"
LDAP_PORT = 20389
# Environment variable
export LDAP_URL="ldap://localhost:20389"
```
### Using with Docker Networks
If your application is also in Docker:
```yaml
# Your app's docker-compose.yml
services:
your-app:
environment:
LDAP_URL: "ldap://ldap-server:389" # Use container name and internal port
networks:
- ldap_docker_ldap-network # Connect to LDAP network
networks:
ldap_docker_ldap-network:
external: true
```
## Quick Reference
```bash
# View current configuration
cat .env | grep PORT
# Generate ldapsearch commands
./scripts/ldapsearch_helper.sh
# Test connection on custom port
make test-connection
# Check what ports containers are using
docker-compose ps
# Change ports (example)
echo "LDAP_PORT=12389" > .env
echo "LDAPS_PORT=12636" >> .env
make down && make start
# Verify new ports work
make test-users
```
## Summary
**To use custom ports:**
1. Edit `LDAP_PORT` and `LDAPS_PORT` in `.env`
2. Run `make down && make start`
3. All tools automatically use your new ports!
**Need ldapsearch commands?**
- Run `./scripts/ldapsearch_helper.sh`
- Or manually replace 389 → your LDAP_PORT, 636 → your LDAPS_PORT
That's it! The port configuration system is designed to be simple and automatic.
---
**See Also:**
- [README.md](README.md) - Full documentation
- [GETTING_STARTED.md](GETTING_STARTED.md) - Setup guide
- [QUICKREF.md](QUICKREF.md) - Command reference

View File

@@ -1,35 +1,33 @@
version: '3.8'
services:
openldap:
image: osixia/openldap:1.5.0
container_name: ldap-server
hostname: ldap.testing.local
container_name: ${LDAP_CONTAINER_NAME:-ldap-server}
hostname: ${LDAP_HOSTNAME:-ldap.testing.local}
environment:
# Base domain configuration
LDAP_ORGANISATION: "Testing Organization"
LDAP_DOMAIN: "testing.local"
LDAP_BASE_DN: "dc=testing,dc=local"
LDAP_ORGANISATION: ${LDAP_ORGANISATION:-Testing Organization}
LDAP_DOMAIN: ${LDAP_DOMAIN:-testing.local}
LDAP_BASE_DN: ${LDAP_BASE_DN:-dc=testing,dc=local}
# Admin credentials (change these for production)
LDAP_ADMIN_PASSWORD: "admin_password"
LDAP_CONFIG_PASSWORD: "config_password"
LDAP_ADMIN_PASSWORD: ${LDAP_ADMIN_PASSWORD:-admin_password}
LDAP_CONFIG_PASSWORD: ${LDAP_CONFIG_PASSWORD:-config_password}
# SSL/TLS Configuration
LDAP_TLS: "true"
LDAP_TLS_CRT_FILENAME: "server.crt"
LDAP_TLS_KEY_FILENAME: "server.key"
LDAP_TLS_CA_CRT_FILENAME: "ca.crt"
LDAP_TLS_VERIFY_CLIENT: "try"
LDAP_TLS: ${LDAP_TLS:-true}
LDAP_TLS_CRT_FILENAME: ${LDAP_TLS_CRT_FILENAME:-server.crt}
LDAP_TLS_KEY_FILENAME: ${LDAP_TLS_KEY_FILENAME:-server.key}
LDAP_TLS_CA_CRT_FILENAME: ${LDAP_TLS_CA_CRT_FILENAME:-ca.crt}
LDAP_TLS_VERIFY_CLIENT: ${LDAP_TLS_VERIFY_CLIENT:-try}
# Logging
LDAP_LOG_LEVEL: "256"
LDAP_LOG_LEVEL: ${LDAP_LOG_LEVEL:-256}
ports:
# Standard LDAP port
- "389:389"
- "${LDAP_PORT:-389}:389"
# LDAPS (SSL) port
- "636:636"
- "${LDAPS_PORT:-636}:636"
volumes:
# Custom certificates - place your dev-ca certs here
@@ -52,12 +50,12 @@ services:
# Optional: phpLDAPadmin for web-based management
phpldapadmin:
image: osixia/phpldapadmin:0.9.0
container_name: ldap-admin
container_name: ${PHPLDAPADMIN_CONTAINER_NAME:-ldap-admin}
environment:
PHPLDAPADMIN_LDAP_HOSTS: "openldap"
PHPLDAPADMIN_HTTPS: "false"
ports:
- "8080:80"
- "${PHPLDAPADMIN_PORT:-8080}:80"
depends_on:
- openldap
networks:

View File

@@ -11,6 +11,7 @@ Usage:
"""
import argparse
import os
import sys
from typing import Dict, List, Optional
@@ -24,7 +25,8 @@ except ImportError:
# Configuration
LDAP_SERVER = "ldap://localhost:389"
LDAP_PORT = os.environ.get("LDAP_PORT", "389")
LDAP_SERVER = f"ldap://localhost:{LDAP_PORT}"
LDAP_BASE_DN = "dc=testing,dc=local"
LDAP_PEOPLE_OU = "ou=people,dc=testing,dc=local"
LDAP_GROUPS_OU = "ou=groups,dc=testing,dc=local"
@@ -104,8 +106,8 @@ class LDAPAuthenticator:
"first_name": str(entry.givenName) if entry.givenName else "",
"last_name": str(entry.sn),
"email": str(entry.mail),
"uid_number": int(entry.uidNumber) if entry.uidNumber else None,
"gid_number": int(entry.gidNumber) if entry.gidNumber else None,
"uid_number": int(str(entry.uidNumber)) if entry.uidNumber else None,
"gid_number": int(str(entry.gidNumber)) if entry.gidNumber else None,
"dn": entry.entry_dn,
}
conn.unbind()

View File

@@ -25,7 +25,7 @@ cn: John Doe
sn: Doe
givenName: John
mail: jdoe@testing.local
userPassword: {SSHA}5en6G6MezRroT3XKqkdPOmY/BFQ= # password: password123
userPassword: {SSHA}Vj/QLoVDZbjklfhV/e6JdTo8MUNRy9dN
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/jdoe
@@ -42,7 +42,7 @@ cn: Jane Smith
sn: Smith
givenName: Jane
mail: jsmith@testing.local
userPassword: {SSHA}5en6G6MezRroT3XKqkdPOmY/BFQ= # password: password123
userPassword: {SSHA}Vj/QLoVDZbjklfhV/e6JdTo8MUNRy9dN
uidNumber: 10002
gidNumber: 10002
homeDirectory: /home/jsmith
@@ -59,7 +59,7 @@ cn: Admin User
sn: User
givenName: Admin
mail: admin@testing.local
userPassword: {SSHA}5en6G6MezRroT3XKqkdPOmY/BFQ= # password: password123
userPassword: {SSHA}Vj/QLoVDZbjklfhV/e6JdTo8MUNRy9dN
uidNumber: 10000
gidNumber: 10000
homeDirectory: /home/admin
@@ -76,7 +76,7 @@ cn: Test User
sn: User
givenName: Test
mail: testuser@testing.local
userPassword: {SSHA}5en6G6MezRroT3XKqkdPOmY/BFQ= # password: password123
userPassword: {SSHA}Vj/QLoVDZbjklfhV/e6JdTo8MUNRy9dN
uidNumber: 10003
gidNumber: 10003
homeDirectory: /home/testuser

View File

@@ -33,8 +33,11 @@ ldap-docker = "scripts.cli:main"
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.uv]
dev-dependencies = [
[tool.hatch.build.targets.wheel]
packages = ["scripts", "tests"]
[dependency-groups]
dev = [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
"black>=23.0.0",

View File

@@ -6,6 +6,7 @@ This tool provides convenient commands for starting, stopping, and testing
the LDAP server, as well as managing test users and certificates.
"""
import os
import subprocess
import sys
import time
@@ -27,8 +28,8 @@ PROJECT_ROOT = Path(__file__).parent.parent
CERTS_DIR = PROJECT_ROOT / "certs"
LDIF_DIR = PROJECT_ROOT / "ldif"
DEFAULT_HOST = "localhost"
DEFAULT_PORT = 389
DEFAULT_LDAPS_PORT = 636
DEFAULT_PORT = int(os.environ.get("LDAP_PORT", "389"))
DEFAULT_LDAPS_PORT = int(os.environ.get("LDAPS_PORT", "636"))
DEFAULT_BASE_DN = "dc=testing,dc=local"
DEFAULT_ADMIN_DN = "cn=admin,dc=testing,dc=local"
DEFAULT_ADMIN_PASSWORD = "admin_password"

195
scripts/ldapsearch_helper.sh Executable file
View File

@@ -0,0 +1,195 @@
#!/usr/bin/env bash
#
# LDAP Search Helper
# Generates ldapsearch commands configured for your environment
#
set -e
# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Get the directory where this script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# Load environment variables from .env if it exists
if [ -f "$PROJECT_ROOT/.env" ]; then
source "$PROJECT_ROOT/.env"
fi
# Set defaults if not in environment
LDAP_PORT=${LDAP_PORT:-389}
LDAPS_PORT=${LDAPS_PORT:-636}
LDAP_BASE_DN=${LDAP_BASE_DN:-dc=testing,dc=local}
LDAP_ADMIN_PASSWORD=${LDAP_ADMIN_PASSWORD:-admin_password}
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}LDAP Search Command Generator${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo "Configuration:"
echo " LDAP Port: $LDAP_PORT"
echo " LDAPS Port: $LDAPS_PORT"
echo " Base DN: $LDAP_BASE_DN"
echo ""
# Function to print a command example
print_cmd() {
local description="$1"
local command="$2"
echo -e "${GREEN}# $description${NC}"
echo -e "${YELLOW}$command${NC}"
echo ""
}
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Basic Connection Tests${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
print_cmd "Test server is responding (anonymous bind)" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -x -b \"\" -s base"
print_cmd "Test with admin credentials" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"$LDAP_BASE_DN\""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Search Users${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
print_cmd "List all users" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=people,$LDAP_BASE_DN\" \"(objectClass=inetOrgPerson)\" uid cn mail"
print_cmd "Search for specific user (jdoe)" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"$LDAP_BASE_DN\" \"(uid=jdoe)\""
print_cmd "Test user authentication (as jdoe)" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"uid=jdoe,ou=people,$LDAP_BASE_DN\" -w password123 -b \"$LDAP_BASE_DN\" \"(uid=jdoe)\""
print_cmd "Get all user attributes for jdoe" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=people,$LDAP_BASE_DN\" \"(uid=jdoe)\" '*' '+'"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Search Groups${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
print_cmd "List all groups" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=groups,$LDAP_BASE_DN\" \"(objectClass=groupOfNames)\" cn member"
print_cmd "Find groups for user jdoe" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=groups,$LDAP_BASE_DN\" \"(member=uid=jdoe,ou=people,$LDAP_BASE_DN)\" cn"
print_cmd "Get members of developers group" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=groups,$LDAP_BASE_DN\" \"(cn=developers)\" member"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}LDAPS (SSL/TLS) Commands${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
print_cmd "Test LDAPS connection" \
"ldapsearch -H ldaps://localhost:$LDAPS_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"$LDAP_BASE_DN\""
print_cmd "LDAPS with CA certificate verification" \
"LDAPTLS_CACERT=$PROJECT_ROOT/certs/ca.crt ldapsearch -H ldaps://localhost:$LDAPS_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"$LDAP_BASE_DN\""
print_cmd "Check SSL certificate" \
"openssl s_client -connect localhost:$LDAPS_PORT -CAfile $PROJECT_ROOT/certs/ca.crt -showcerts"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Secure Commands (Password Prompt)${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
print_cmd "Admin search with password prompt (more secure)" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -W -b \"$LDAP_BASE_DN\""
print_cmd "User authentication with password prompt" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"uid=jdoe,ou=people,$LDAP_BASE_DN\" -W -b \"$LDAP_BASE_DN\" \"(uid=jdoe)\""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Advanced Queries${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
print_cmd "Search with wildcard (all users starting with 'j')" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=people,$LDAP_BASE_DN\" \"(uid=j*)\" uid cn"
print_cmd "Search by email domain" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=people,$LDAP_BASE_DN\" \"(mail=*@testing.local)\" uid mail"
print_cmd "Count total users" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"ou=people,$LDAP_BASE_DN\" \"(objectClass=inetOrgPerson)\" dn | grep -c '^dn:'"
print_cmd "Export entire directory to LDIF file" \
"ldapsearch -H ldap://localhost:$LDAP_PORT -D \"cn=admin,$LDAP_BASE_DN\" -w $LDAP_ADMIN_PASSWORD -b \"$LDAP_BASE_DN\" -LLL > ldap_backup.ldif"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Quick Reference${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo "Common flags:"
echo " -H : LDAP URI (ldap:// or ldaps://)"
echo " -D : Bind DN (user to authenticate as)"
echo " -w : Password (visible in process list)"
echo " -W : Prompt for password (more secure)"
echo " -x : Use simple authentication"
echo " -b : Base DN to search from"
echo " -s : Scope (base, one, sub)"
echo " -LLL: LDIF output without comments"
echo ""
echo "Test credentials:"
echo " Admin: cn=admin,$LDAP_BASE_DN / $LDAP_ADMIN_PASSWORD"
echo " Test user: uid=jdoe,ou=people,$LDAP_BASE_DN / password123"
echo ""
echo -e "${GREEN}Tip:${NC} Copy any command above and run it in your terminal!"
echo ""
# Option to run a command interactively
if [ "$1" = "--interactive" ] || [ "$1" = "-i" ]; then
echo ""
echo "Select a command to run:"
echo " 1) List all users"
echo " 2) Search for user jdoe"
echo " 3) Test user authentication"
echo " 4) List all groups"
echo " 5) Test LDAPS connection"
echo " 6) Custom command"
echo ""
read -p "Choice (1-6): " choice
case $choice in
1)
ldapsearch -H ldap://localhost:$LDAP_PORT -D "cn=admin,$LDAP_BASE_DN" -w $LDAP_ADMIN_PASSWORD -b "ou=people,$LDAP_BASE_DN" "(objectClass=inetOrgPerson)" uid cn mail
;;
2)
ldapsearch -H ldap://localhost:$LDAP_PORT -D "cn=admin,$LDAP_BASE_DN" -w $LDAP_ADMIN_PASSWORD -b "$LDAP_BASE_DN" "(uid=jdoe)"
;;
3)
read -p "Enter password for jdoe: " -s user_pass
echo ""
ldapsearch -H ldap://localhost:$LDAP_PORT -D "uid=jdoe,ou=people,$LDAP_BASE_DN" -w "$user_pass" -b "$LDAP_BASE_DN" "(uid=jdoe)"
;;
4)
ldapsearch -H ldap://localhost:$LDAP_PORT -D "cn=admin,$LDAP_BASE_DN" -w $LDAP_ADMIN_PASSWORD -b "ou=groups,$LDAP_BASE_DN" "(objectClass=groupOfNames)" cn member
;;
5)
LDAPTLS_CACERT=$PROJECT_ROOT/certs/ca.crt ldapsearch -H ldaps://localhost:$LDAPS_PORT -D "cn=admin,$LDAP_BASE_DN" -w $LDAP_ADMIN_PASSWORD -b "$LDAP_BASE_DN"
;;
6)
read -p "Enter custom filter: " filter
ldapsearch -H ldap://localhost:$LDAP_PORT -D "cn=admin,$LDAP_BASE_DN" -w $LDAP_ADMIN_PASSWORD -b "$LDAP_BASE_DN" "$filter"
;;
*)
echo "Invalid choice"
exit 1
;;
esac
fi