Release v0.1.0

- Initial release of LDAP Docker development tool
- Full .env configuration support with comprehensive documentation
- Pre-configured test users and SSL/TLS support
- Consolidated documentation in README
This commit is contained in:
2025-10-20 12:32:48 -07:00
parent 857c71484a
commit 7db3584ad3
16 changed files with 552 additions and 2618 deletions

View File

@@ -5,9 +5,7 @@ This package contains management and utility scripts for the LDAP Docker
development environment.
Modules:
- cli: Command-line interface for managing LDAP server
- generate_certs: SSL/TLS certificate generation utility
"""
__version__ = "0.1.0"
__all__ = ["cli", "generate_certs"]

View File

@@ -1,464 +0,0 @@
#!/usr/bin/env python3
"""
CLI tool for managing the LDAP Docker development environment.
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
from pathlib import Path
from typing import Optional
import click
try:
import ldap3
from ldap3 import ALL, Connection, Server
from ldap3.core.exceptions import LDAPException
except ImportError:
ldap3 = None
# Constants
PROJECT_ROOT = Path(__file__).parent.parent
CERTS_DIR = PROJECT_ROOT / "certs"
LDIF_DIR = PROJECT_ROOT / "ldif"
DEFAULT_HOST = "localhost"
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"
def run_command(cmd: list[str], cwd: Optional[Path] = None, check: bool = True) -> subprocess.CompletedProcess:
"""Run a shell command and return the result."""
if cwd is None:
cwd = PROJECT_ROOT
try:
result = subprocess.run(
cmd,
cwd=cwd,
capture_output=True,
text=True,
check=check,
)
return result
except subprocess.CalledProcessError as e:
click.echo(f"Error running command: {' '.join(cmd)}", err=True)
click.echo(f"Exit code: {e.returncode}", err=True)
if e.stdout:
click.echo(f"stdout: {e.stdout}", err=True)
if e.stderr:
click.echo(f"stderr: {e.stderr}", err=True)
raise
def check_docker():
"""Check if Docker is available."""
try:
result = run_command(["docker", "version"], check=False)
if result.returncode != 0:
click.echo("Error: Docker is not running or not installed.", err=True)
click.echo("Please ensure Docker (or Rancher Desktop) is running.", err=True)
sys.exit(1)
except FileNotFoundError:
click.echo("Error: Docker command not found.", err=True)
click.echo("Please install Docker or Rancher Desktop.", err=True)
sys.exit(1)
def check_certificates():
"""Check if SSL certificates exist."""
required_files = ["ca.crt", "server.crt", "server.key"]
missing = [f for f in required_files if not (CERTS_DIR / f).exists()]
if missing:
click.echo("⚠️ Warning: Missing SSL certificate files:", err=True)
for f in missing:
click.echo(f" - {CERTS_DIR / f}", err=True)
click.echo("\nYou can:", err=True)
click.echo(" 1. Copy your dev-ca certificates to the certs/ directory", err=True)
click.echo(" 2. Generate self-signed certificates: ldap-docker certs generate", err=True)
return False
return True
@click.group()
@click.version_option(version="0.1.0")
def cli():
"""LDAP Docker Development Tool - Manage your OpenLDAP development environment."""
pass
@cli.group()
def server():
"""Manage the LDAP server container."""
pass
@server.command("start")
@click.option("--detach", "-d", is_flag=True, default=True, help="Run in detached mode")
@click.option("--build", is_flag=True, help="Build images before starting")
def server_start(detach: bool, build: bool):
"""Start the LDAP server and optional phpLDAPadmin."""
check_docker()
check_certificates()
cmd = ["docker-compose", "up"]
if detach:
cmd.append("-d")
if build:
cmd.append("--build")
click.echo("Starting LDAP server...")
result = run_command(cmd)
if result.returncode == 0:
click.echo("✅ LDAP server started successfully!")
click.echo(f"\nLDAP server is available at:")
click.echo(f" - LDAP: ldap://localhost:389")
click.echo(f" - LDAPS: ldaps://localhost:636")
click.echo(f" - Admin: http://localhost:8080 (phpLDAPadmin)")
click.echo(f"\nAdmin credentials:")
click.echo(f" - DN: {DEFAULT_ADMIN_DN}")
click.echo(f" - Password: {DEFAULT_ADMIN_PASSWORD}")
if detach:
click.echo("\nWaiting for server to be ready...")
time.sleep(5)
# Try to check if server is responding
result = run_command(
["docker-compose", "ps", "--filter", "status=running"],
check=False
)
if "ldap-server" in result.stdout:
click.echo("✅ Server is running")
@server.command("stop")
def server_stop():
"""Stop the LDAP server."""
check_docker()
click.echo("Stopping LDAP server...")
run_command(["docker-compose", "stop"])
click.echo("✅ LDAP server stopped")
@server.command("restart")
def server_restart():
"""Restart the LDAP server."""
check_docker()
click.echo("Restarting LDAP server...")
run_command(["docker-compose", "restart"])
click.echo("✅ LDAP server restarted")
click.echo("\nWaiting for server to be ready...")
time.sleep(5)
@server.command("down")
@click.option("--volumes", "-v", is_flag=True, help="Remove volumes (deletes all data)")
def server_down(volumes: bool):
"""Stop and remove the LDAP server containers."""
check_docker()
cmd = ["docker-compose", "down"]
if volumes:
if not click.confirm("⚠️ This will delete all LDAP data. Continue?"):
click.echo("Aborted.")
return
cmd.append("-v")
click.echo("Removing LDAP server containers...")
run_command(cmd)
click.echo("✅ Containers removed")
@server.command("logs")
@click.option("--follow", "-f", is_flag=True, help="Follow log output")
@click.option("--tail", "-n", default=100, help="Number of lines to show from the end")
@click.option("--service", default="openldap", help="Service to show logs for")
def server_logs(follow: bool, tail: int, service: str):
"""View LDAP server logs."""
check_docker()
cmd = ["docker-compose", "logs", f"--tail={tail}"]
if follow:
cmd.append("-f")
cmd.append(service)
# For follow mode, we want to pass through to the terminal
try:
subprocess.run(cmd, cwd=PROJECT_ROOT)
except KeyboardInterrupt:
click.echo("\n")
@server.command("status")
def server_status():
"""Check LDAP server status."""
check_docker()
result = run_command(["docker-compose", "ps"], check=False)
click.echo(result.stdout)
@cli.group()
def certs():
"""Manage SSL/TLS certificates."""
pass
@certs.command("generate")
@click.option("--force", is_flag=True, help="Overwrite existing certificates")
@click.option("--hostname", default="ldap.testing.local", help="Server hostname")
def certs_generate(force: bool, hostname: str):
"""Generate self-signed SSL certificates for development."""
script_path = PROJECT_ROOT / "scripts" / "generate_certs.py"
if not script_path.exists():
click.echo(f"Error: Certificate generation script not found: {script_path}", err=True)
sys.exit(1)
cmd = [sys.executable, str(script_path), "--hostname", hostname]
if force:
cmd.append("--force")
try:
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError:
click.echo("Failed to generate certificates", err=True)
sys.exit(1)
@certs.command("check")
def certs_check():
"""Verify SSL certificates."""
required_files = {
"ca.crt": "CA Certificate",
"server.crt": "Server Certificate",
"server.key": "Server Private Key",
}
click.echo("Checking SSL certificates...\n")
all_exist = True
for filename, description in required_files.items():
filepath = CERTS_DIR / filename
if filepath.exists():
size = filepath.stat().st_size
click.echo(f"{description}: {filepath} ({size} bytes)")
else:
click.echo(f"{description}: {filepath} (missing)")
all_exist = False
if all_exist:
click.echo("\n✅ All required certificates are present")
# Try to verify the certificate chain
try:
result = run_command([
"openssl", "verify", "-CAfile",
str(CERTS_DIR / "ca.crt"),
str(CERTS_DIR / "server.crt")
], check=False)
if result.returncode == 0:
click.echo("✅ Certificate chain is valid")
else:
click.echo("⚠️ Certificate chain verification failed")
click.echo(result.stderr)
except FileNotFoundError:
click.echo(" OpenSSL not found, skipping certificate verification")
else:
click.echo("\n❌ Some certificates are missing")
click.echo("Run 'ldap-docker certs generate' to create them")
sys.exit(1)
@cli.group()
def test():
"""Test LDAP server connectivity and queries."""
pass
@test.command("connection")
@click.option("--host", default=DEFAULT_HOST, help="LDAP server host")
@click.option("--port", default=DEFAULT_PORT, help="LDAP server port")
@click.option("--use-ssl", is_flag=True, help="Use LDAPS instead of LDAP")
def test_connection(host: str, port: int, use_ssl: bool):
"""Test basic connection to LDAP server."""
if ldap3 is None:
click.echo("Error: ldap3 library not installed", err=True)
click.echo("Install it with: uv pip install ldap3", err=True)
sys.exit(1)
if use_ssl:
port = DEFAULT_LDAPS_PORT
url = f"ldaps://{host}:{port}"
else:
url = f"ldap://{host}:{port}"
click.echo(f"Testing connection to {url}...")
try:
server = Server(url, get_info=ALL, use_ssl=use_ssl)
conn = Connection(server, auto_bind=True)
click.echo("✅ Successfully connected to LDAP server")
click.echo(f"\nServer info:")
click.echo(f" Vendor: {server.info.vendor_name if server.info else 'Unknown'}")
click.echo(f" Version: {server.info.vendor_version if server.info else 'Unknown'}")
conn.unbind()
except LDAPException as e:
click.echo(f"❌ Connection failed: {e}", err=True)
sys.exit(1)
@test.command("auth")
@click.option("--host", default=DEFAULT_HOST, help="LDAP server host")
@click.option("--port", default=DEFAULT_PORT, help="LDAP server port")
@click.option("--use-ssl", is_flag=True, help="Use LDAPS")
@click.option("--user", default=DEFAULT_ADMIN_DN, help="User DN")
@click.option("--password", default=DEFAULT_ADMIN_PASSWORD, help="Password")
def test_auth(host: str, port: int, use_ssl: bool, user: str, password: str):
"""Test authentication with LDAP server."""
if ldap3 is None:
click.echo("Error: ldap3 library not installed", err=True)
click.echo("Install it with: uv pip install ldap3", err=True)
sys.exit(1)
if use_ssl:
port = DEFAULT_LDAPS_PORT
url = f"ldaps://{host}:{port}"
else:
url = f"ldap://{host}:{port}"
click.echo(f"Testing authentication to {url}...")
click.echo(f"User: {user}")
try:
server = Server(url, get_info=ALL, use_ssl=use_ssl)
conn = Connection(server, user=user, password=password, auto_bind=True)
click.echo("✅ Authentication successful")
# Try to perform a simple search
conn.search(DEFAULT_BASE_DN, "(objectClass=*)", search_scope="BASE")
if conn.entries:
click.echo(f"✅ Base DN accessible: {DEFAULT_BASE_DN}")
conn.unbind()
except LDAPException as e:
click.echo(f"❌ Authentication failed: {e}", err=True)
sys.exit(1)
@test.command("users")
@click.option("--host", default=DEFAULT_HOST, help="LDAP server host")
@click.option("--port", default=DEFAULT_PORT, help="LDAP server port")
@click.option("--use-ssl", is_flag=True, help="Use LDAPS")
def test_users(host: str, port: int, use_ssl: bool):
"""List all users in the LDAP directory."""
if ldap3 is None:
click.echo("Error: ldap3 library not installed", err=True)
click.echo("Install it with: uv pip install ldap3", err=True)
sys.exit(1)
if use_ssl:
port = DEFAULT_LDAPS_PORT
url = f"ldaps://{host}:{port}"
else:
url = f"ldap://{host}:{port}"
try:
server = Server(url, get_info=ALL, use_ssl=use_ssl)
conn = Connection(
server,
user=DEFAULT_ADMIN_DN,
password=DEFAULT_ADMIN_PASSWORD,
auto_bind=True
)
# Search for all users
conn.search(
DEFAULT_BASE_DN,
"(objectClass=inetOrgPerson)",
attributes=["uid", "cn", "mail", "uidNumber"]
)
if conn.entries:
click.echo(f"Found {len(conn.entries)} user(s):\n")
for entry in conn.entries:
click.echo(f" - {entry.cn}: {entry.uid} ({entry.mail})")
else:
click.echo("No users found")
conn.unbind()
except LDAPException as e:
click.echo(f"❌ Query failed: {e}", err=True)
sys.exit(1)
@cli.command("init")
def init():
"""Initialize the LDAP Docker environment."""
click.echo("Initializing LDAP Docker environment...\n")
# Check Docker
click.echo("1. Checking Docker...")
check_docker()
click.echo(" ✅ Docker is available\n")
# Check certificates
click.echo("2. Checking SSL certificates...")
if not check_certificates():
if click.confirm("\nGenerate self-signed certificates now?", default=True):
certs_generate.callback(force=False, hostname="ldap.testing.local")
else:
click.echo("\n You can generate certificates later with: ldap-docker certs generate")
click.echo(" Or copy your dev-ca certificates to the certs/ directory")
else:
click.echo(" ✅ Certificates are present\n")
# Start server
click.echo("\n3. Starting LDAP server...")
if click.confirm("Start the LDAP server now?", default=True):
server_start.callback(detach=True, build=False)
else:
click.echo("\n You can start the server later with: ldap-docker server start")
click.echo("\n✅ Initialization complete!")
click.echo("\nUseful commands:")
click.echo(" - View logs: ldap-docker server logs -f")
click.echo(" - Test connection: ldap-docker test connection")
click.echo(" - List users: ldap-docker test users")
click.echo(" - Stop server: ldap-docker server stop")
def main():
"""Entry point for the CLI."""
try:
cli()
except KeyboardInterrupt:
click.echo("\n\nInterrupted by user")
sys.exit(130)
except Exception as e:
click.echo(f"Error: {e}", err=True)
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -9,7 +9,7 @@ For production, use proper certificates from your dev-ca or a trusted CA.
import argparse
import ipaddress
import sys
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from pathlib import Path
try:
@@ -17,7 +17,7 @@ try:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import ExtensionOID, NameOID
from cryptography.x509.oid import ExtendedKeyUsageOID, NameOID
except ImportError:
print("Error: cryptography library not found.")
print("Install it with: uv pip install cryptography")
@@ -55,8 +55,8 @@ def generate_ca_certificate(
.issuer_name(issuer)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow())
.not_valid_after(datetime.utcnow() + timedelta(days=days_valid))
.not_valid_before(datetime.now(timezone.utc))
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=days_valid))
.add_extension(
x509.BasicConstraints(ca=True, path_length=None),
critical=True,
@@ -90,7 +90,7 @@ def generate_server_certificate(
ca_cert: x509.Certificate,
ca_key: rsa.RSAPrivateKey,
hostname: str = "ldap.testing.local",
san_list: list[str] = None,
san_list: list[str] | None = None,
days_valid: int = 365,
) -> x509.Certificate:
"""Generate a server certificate signed by the CA."""
@@ -123,8 +123,8 @@ def generate_server_certificate(
.issuer_name(ca_cert.subject)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow())
.not_valid_after(datetime.utcnow() + timedelta(days=days_valid))
.not_valid_before(datetime.now(timezone.utc))
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=days_valid))
.add_extension(
x509.SubjectAlternativeName(san_entries),
critical=False,
@@ -148,7 +148,7 @@ def generate_server_certificate(
critical=True,
)
.add_extension(
x509.ExtendedKeyUsage([x509.ExtendedKeyUsageOID.SERVER_AUTH]),
x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),
critical=False,
)
.add_extension(
@@ -236,9 +236,7 @@ def main():
# Check if certificates already exist
if not args.force:
existing = [
p for p in [ca_cert_path, server_cert_path, server_key_path] if p.exists()
]
existing = [p for p in [ca_cert_path, server_cert_path, server_key_path] if p.exists()]
if existing:
print("Error: The following certificate files already exist:")
for p in existing:

View File

@@ -1,195 +0,0 @@
#!/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