{"id":25839735,"url":"https://github.com/netresearch/simple-ldap-go","last_synced_at":"2026-04-22T01:08:12.556Z","repository":{"id":176830792,"uuid":"659621314","full_name":"netresearch/simple-ldap-go","owner":"netresearch","description":"A simple LDAP wrapper around github.com/go-ldap/ldap/v3","archived":false,"fork":false,"pushed_at":"2025-01-30T08:14:59.000Z","size":49,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-30T09:23:12.861Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/netresearch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-28T08:06:06.000Z","updated_at":"2025-01-30T08:14:50.000Z","dependencies_parsed_at":"2024-01-10T17:13:42.715Z","dependency_job_id":"fcda1249-60af-4170-9497-c8a37e3861e2","html_url":"https://github.com/netresearch/simple-ldap-go","commit_stats":null,"previous_names":["netresearch/simple-ldap-go"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netresearch%2Fsimple-ldap-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netresearch%2Fsimple-ldap-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netresearch%2Fsimple-ldap-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netresearch%2Fsimple-ldap-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/netresearch","download_url":"https://codeload.github.com/netresearch/simple-ldap-go/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241317608,"owners_count":19943199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-01T04:34:14.148Z","updated_at":"2026-04-22T01:08:12.548Z","avatar_url":"https://github.com/netresearch.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simple LDAP Go\n\n[![Template Drift](https://github.com/netresearch/simple-ldap-go/actions/workflows/check-template-drift.yml/badge.svg)](https://github.com/netresearch/simple-ldap-go/actions/workflows/check-template-drift.yml)\n[![managed by netresearch/.github templates](https://img.shields.io/badge/template-netresearch%2F.github-2F99A4?logo=github)](https://github.com/netresearch/.github/tree/main/templates/go-app)\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/netresearch/simple-ldap-go.svg)](https://pkg.go.dev/github.com/netresearch/simple-ldap-go)\n[![Go Report Card](https://goreportcard.com/badge/github.com/netresearch/simple-ldap-go)](https://goreportcard.com/report/github.com/netresearch/simple-ldap-go)\n[![CI Status](https://github.com/netresearch/simple-ldap-go/actions/workflows/optimized-tests.yml/badge.svg)](https://github.com/netresearch/simple-ldap-go/actions/workflows/optimized-tests.yml)\n[![codecov](https://codecov.io/gh/netresearch/simple-ldap-go/graph/badge.svg)](https://codecov.io/gh/netresearch/simple-ldap-go)\n[![Go Version](https://img.shields.io/github/go-mod/go-version/netresearch/simple-ldap-go)](https://go.dev/dl/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Latest Release](https://img.shields.io/github/v/release/netresearch/simple-ldap-go)](https://github.com/netresearch/simple-ldap-go/releases)\n[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/netresearch/simple-ldap-go/graphs/commit-activity)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/netresearch/simple-ldap-go/pulls)\n\nA simple Go library providing an easy-to-use wrapper around [go-ldap/ldap/v3](https://github.com/go-ldap/ldap) for common LDAP and Active Directory operations.\n\nThis package was extracted from [netresearch/raybeam](https://github.com/netresearch/raybeam) to provide a standalone, reusable LDAP client library.\n\n## Why Use Simple LDAP Go?\n\nWorking with [go-ldap/ldap/v3](https://github.com/go-ldap/ldap) directly can be challenging for common LDAP operations. This library solves the pain points you'll encounter:\n\n### Problems with Raw go-ldap\n\n❌ **Complex Connection Management** - Manual connection pooling, health checks, and retry logic\n❌ **Manual DN Construction** - Error-prone string building with security risks (DN injection)\n❌ **No Caching** - Repeated LDAP queries for the same data slow down applications\n❌ **Verbose Error Handling** - Generic LDAP errors without context or specific types\n❌ **AD vs OpenLDAP Differences** - Different APIs and attributes require separate code paths\n❌ **Security Pitfalls** - Easy to introduce vulnerabilities without proper input validation\n❌ **Boilerplate Code** - Simple operations require dozens of lines of setup and teardown\n\n### How Simple LDAP Go Solves These\n\n✅ **Automatic Connection Pooling** - Built-in connection management with health checks and auto-retry\n✅ **Safe DN Handling** - Automatic escaping and validation prevents injection attacks\n✅ **Built-in Caching** - Intelligent caching layer reduces LDAP server load\n✅ **Comprehensive Error Types** - Specific errors like `ErrUserNotFound` with detailed context\n✅ **Unified API** - Same methods work seamlessly with Active Directory and OpenLDAP\n✅ **Security by Default** - Input validation, proper escaping, and secure connection handling\n✅ **Simple API** - Common operations in just a few lines of code\n\n### Code Comparison\n\n**Raw go-ldap**: Finding and authenticating a user (50+ lines)\n```go\nimport \"github.com/go-ldap/ldap/v3\"\n\n// Connect and bind\nconn, err := ldap.DialURL(\"ldaps://ldap.example.com:636\")\nif err != nil {\n    return err\n}\ndefer conn.Close()\n\nerr = conn.Bind(\"cn=admin,dc=example,dc=com\", \"password\")\nif err != nil {\n    return err\n}\n\n// Search for user (manual filter construction)\nsearchReq := ldap.NewSearchRequest(\n    \"dc=example,dc=com\",\n    ldap.ScopeWholeSubtree,\n    ldap.NeverDerefAliases,\n    0, 0, false,\n    fmt.Sprintf(\"(\u0026(objectClass=user)(sAMAccountName=%s))\",\n        ldap.EscapeFilter(username)), // Manual escaping required\n    []string{\"dn\", \"cn\", \"mail\"},\n    nil,\n)\n\nsr, err := conn.Search(searchReq)\nif err != nil {\n    return err\n}\nif len(sr.Entries) == 0 {\n    return errors.New(\"user not found\") // Generic error\n}\n\nuserDN := sr.Entries[0].DN\n\n// Authenticate user (separate bind operation)\nerr = conn.Bind(userDN, password)\nif err != nil {\n    return err\n}\n// ... additional validation and error handling\n```\n\n**Simple LDAP Go**: Same operation (3 lines)\n```go\nimport ldap \"github.com/netresearch/simple-ldap-go\"\n\nclient, _ := ldap.New(config, \"cn=admin,dc=example,dc=com\", \"password\")\nuser, err := client.CheckPasswordForSAMAccountName(\"username\", \"password\")\n// Returns structured User object with automatic error handling\n```\n\n## Features\n\n- 🔐 **User Authentication** - One-line password verification with automatic DN resolution and secure binding\n- 👥 **User Management** - Type-safe user operations with automatic attribute mapping and validation\n- 🏢 **Group Operations** - Simplified group queries and membership management across AD and OpenLDAP\n- 💻 **Computer Management** - Active Directory computer object support with automatic schema detection\n- 🔑 **Password Management** - Secure password changes and admin resets with automatic LDAPS enforcement and policy validation\n- 🛡️ **Active Directory Support** - Native AD features like SAMAccountName, UPN, and nested group resolution\n- ⚡ **Connection Pooling** - Automatic connection management with health checks, retry logic, and resource cleanup\n- 🎯 **Smart Caching** - Configurable caching layer that reduces server load for repeated queries\n- 🔒 **Security by Default** - Built-in DN injection protection, input validation, and secure connection handling\n- 📊 **Structured Errors** - Context-rich error types that make debugging and error handling straightforward\n- 🌐 **Context Support** - Full `context.Context` integration for timeouts, cancellation, and request tracing\n- 📝 **Structured Logging** - Integrated slog support for comprehensive operational visibility\n\n## Installation\n\n```bash\ngo get github.com/netresearch/simple-ldap-go\n```\n\n## Quick Start\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \n    ldap \"github.com/netresearch/simple-ldap-go\"\n)\n\nfunc main() {\n    // Configure LDAP connection\n    config := ldap.Config{\n        Server:            \"ldaps://ldap.example.com:636\",\n        BaseDN:            \"dc=example,dc=com\",\n        IsActiveDirectory: true, // Set to false for generic LDAP\n    }\n\n    // Create client with service account credentials\n    client, err := ldap.New(config, \"cn=admin,dc=example,dc=com\", \"password\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Authenticate a user\n    user, err := client.CheckPasswordForSAMAccountName(\"username\", \"password\")\n    if err != nil {\n        log.Printf(\"Authentication failed: %v\", err)\n        return\n    }\n    \n    fmt.Printf(\"Welcome, %s!\\n\", user.CN())\n}\n```\n\n## Examples\n\nComprehensive examples are available in the [examples](examples/) directory:\n\n- **[Basic Usage](examples/basic-usage/)** - Finding users, groups, and computers\n- **[Authentication](examples/authentication/)** - User authentication, password changes, and admin resets  \n- **[User Management](examples/user-management/)** - Creating, updating, and managing users\n\n## API Reference\n\n### Core Types\n\n- **`Config`** - LDAP server configuration\n- **`LDAP`** - Main client for LDAP operations\n- **`User`** - Represents an LDAP user with common attributes\n- **`Group`** - Represents an LDAP group with member information\n- **`Computer`** - Represents a computer object (Active Directory)\n\n### Key Operations\n\n```go\n// Basic client creation\nclient, err := ldap.New(config, username, password)\n\n// Enhanced client with connection pooling and caching\nclient, err := ldap.NewHighPerformanceClient(config, username, password)\n// Or with custom configuration:\nclient, err := ldap.NewCachedClient(config, username, password, 1000, 5*time.Minute)\n\n// Convenience constructors\nclient, err := ldap.NewHighPerformanceClient(config, username, password)\nclient, err := ldap.NewCachedClient(config, username, password, 1000, 5*time.Minute)\n\n// User authentication\nuser, err := client.CheckPasswordForSAMAccountName(\"jdoe\", \"password\")\n\n// Find users (standard methods)\nuser, err := client.FindUserBySAMAccountName(\"jdoe\")\nusers, err := client.FindUsers()\n\n// Find users (caching is transparent if enabled in config)\nuser, err := client.FindUserBySAMAccountNameContext(ctx, \"jdoe\")\n// Caching happens automatically if config.EnableCache is true\n\n// User management\nerr := client.CreateUser(fullUser, \"ou=Users,dc=example,dc=com\")\nerr := client.DeleteUser(\"cn=John Doe,ou=Users,dc=example,dc=com\")\n\n// Group operations (caching is transparent if enabled)\ngroup, err := client.FindGroupByDNContext(ctx, \"cn=Admins,dc=example,dc=com\")\n// Caching happens automatically if config.EnableCache is true\nerr := client.AddUserToGroup(userDN, groupDN)\n\n// Password management\nerr := client.ChangePasswordForSAMAccountName(\"jdoe\", \"oldPass\", \"newPass\")\nerr := client.ResetPasswordForSAMAccountName(\"jdoe\", \"newPass\") // Admin reset\n```\n\nSee the [Go Reference](https://pkg.go.dev/github.com/netresearch/simple-ldap-go) for complete API documentation.\n\n## Configuration\n\n### Basic Configuration\n\n#### Generic LDAP Server\n```go\nconfig := ldap.Config{\n    Server:            \"ldap://ldap.example.com:389\",\n    BaseDN:            \"dc=example,dc=com\",\n    IsActiveDirectory: false,\n}\n```\n\n#### Microsoft Active Directory\n```go\nconfig := ldap.Config{\n    Server:            \"ldaps://ad.example.com:636\", // LDAPS recommended\n    BaseDN:            \"dc=example,dc=com\",\n    IsActiveDirectory: true, // Enables AD-specific features\n}\n```\n\n### Performance Configuration\n\nEnable optimization features using configuration flags:\n\n```go\nconfig := ldap.Config{\n    Server:               \"ldaps://ad.example.com:636\",\n    BaseDN:               \"dc=example,dc=com\",\n    IsActiveDirectory:    true,\n\n    // Performance optimizations\n    EnableOptimizations:  true, // Enable all optimizations\n    EnableCache:         true,  // Enable caching separately\n    EnableMetrics:       true,  // Enable performance metrics\n    EnableBulkOps:       true,  // Enable bulk operations\n}\n```\n\nOr configure specific features:\n\n```go\n// High-performance client with all optimizations\nclient, err := ldap.NewHighPerformanceClient(config, username, password)\n\n// Custom configuration with specific features\n// Use config flags to enable features:\nconfig.EnableOptimizations = true  // Enable all optimizations\nconfig.EnableCache = true         // Enable caching\nconfig.EnableMetrics = true       // Enable metrics\nconfig.EnableBulkOps = true       // Enable bulk operations\n\n// Then create client with convenience constructors:\nclient, err := ldap.NewHighPerformanceClient(config, username, password)\n// Or:\nclient, err := ldap.NewCachedClient(config, username, password, 1000, 5*time.Minute)\n// Or:\nclient, err := ldap.NewPooledClient(config, username, password, 20)\n```\n\n## Security Best Practices\n\n- ✅ **Use LDAPS** (TLS encryption) in production environments\n- ✅ **Use service accounts** with minimal required permissions\n- ✅ **Store credentials securely** using environment variables or key management\n- ✅ **Validate certificates** in production deployments\n- ⚠️ **Password changes require LDAPS** when using Active Directory\n\n## Error Handling\n\nThe library provides specific error types for common scenarios:\n\n```go\n// Check for specific errors\n_, err := client.FindUserBySAMAccountName(\"username\")\nif err == ldap.ErrUserNotFound {\n    // Handle user not found\n} else if err != nil {\n    // Handle other errors\n}\n```\n\nAvailable error types:\n- `ErrUserNotFound` - User lookup failed\n- `ErrGroupNotFound` - Group lookup failed\n- `ErrComputerNotFound` - Computer lookup failed\n- `ErrSAMAccountNameDuplicated` - Account name already exists\n- `ErrMailDuplicated` - Email address already exists\n- `ErrActiveDirectoryMustBeLDAPS` - LDAPS required for AD operations\n\n## Requirements\n\n- Go 1.23.0 or later\n- Access to an LDAP server (OpenLDAP, Active Directory, etc.)\n- Appropriate credentials and permissions for desired operations\n\n## Testing\n\nTests require a live LDAP server. Set the following environment variables:\n\n```bash\nexport LDAP_SERVER=\"ldaps://your-server:636\"\nexport LDAP_BASE_DN=\"dc=example,dc=com\" \nexport LDAP_READ_USER=\"cn=service,dc=example,dc=com\"\nexport LDAP_READ_PASSWORD=\"password\"\n```\n\nThen run tests:\n```bash\ngo test -v ./...\n```\n\n## License\n\nThis package is licensed under the MIT License. See the included [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch\n3. Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for commit messages\n4. Use `gofmt` for code formatting\n5. Add tests for new functionality\n6. Submit a pull request\n\n## Related Projects\n\n- [go-ldap/ldap](https://github.com/go-ldap/ldap) - The underlying LDAP library\n- [netresearch/raybeam](https://github.com/netresearch/raybeam) - Original project this was extracted from\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetresearch%2Fsimple-ldap-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetresearch%2Fsimple-ldap-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetresearch%2Fsimple-ldap-go/lists"}