{"id":13413596,"url":"https://github.com/jimlambrt/gldap","last_synced_at":"2025-04-05T03:12:28.336Z","repository":{"id":39200294,"uuid":"447018389","full_name":"jimlambrt/gldap","owner":"jimlambrt","description":"Build LDAP services w/ Go","archived":false,"fork":false,"pushed_at":"2024-10-18T22:33:06.000Z","size":236,"stargazers_count":114,"open_issues_count":1,"forks_count":5,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-29T02:09:14.166Z","etag":null,"topics":["go","golang","ldap","ldap-library","ldap-server","ldap-service","ldap-testing"],"latest_commit_sha":null,"homepage":"","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/jimlambrt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING-add-commands.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-11T23:57:45.000Z","updated_at":"2025-02-26T03:27:13.000Z","dependencies_parsed_at":"2022-09-11T15:00:37.842Z","dependency_job_id":"782812b4-d33f-44ea-aa73-09156ba66d86","html_url":"https://github.com/jimlambrt/gldap","commit_stats":{"total_commits":90,"total_committers":5,"mean_commits":18.0,"dds":"0.48888888888888893","last_synced_commit":"8f791d94f5d2790fe09352ee834506ed07e6c099"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimlambrt%2Fgldap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimlambrt%2Fgldap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimlambrt%2Fgldap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimlambrt%2Fgldap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jimlambrt","download_url":"https://codeload.github.com/jimlambrt/gldap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247280272,"owners_count":20912967,"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":["go","golang","ldap","ldap-library","ldap-server","ldap-service","ldap-testing"],"created_at":"2024-07-30T20:01:44.098Z","updated_at":"2025-04-05T03:12:28.308Z","avatar_url":"https://github.com/jimlambrt.png","language":"Go","funding_links":[],"categories":["Networking","开源类库","网络","Open source library","Repositories"],"sub_categories":["Transliteration","网络","音译","The Internet","Uncategorized"],"readme":"# gldap\n[![Go Reference](https://pkg.go.dev/badge/github.com/jimlambrt/gldap/gldap.svg)](https://pkg.go.dev/github.com/jimlambrt/gldap)\n[![Go Coverage](https://raw.githack.com/jimlambrt/gldap/main/coverage/coverage.svg)](https://raw.githack.com/jimlambrt/gldap/main/coverage/coverage.html)\n[![Go Report Card](https://goreportcard.com/badge/github.com/jimlambrt/gldap)](https://goreportcard.com/report/github.com/jimlambrt/gldap)\n\n\u003chr\u003e\n\n`gldap` is a framework for building LDAP services.  Among other things, it defines abstractions for:\n\n* `Server`: supports both LDAP and LDAPS (TLS) protocols as well as the StartTLS\n  requests. \n* `Request`: represents an LDAP request (bind, search, extended, etc) along with\n  the inbound request message. \n* `ResponseWriter`: allows you to compose request responses.\n* `Mux`: an ldap request multiplexer. It matches the inbound request against a\n  list of registered route handlers. \n* `HandlerFunc`: handlers provided to the Mux which serve individual ldap requests.\n\n\u003chr\u003e\n\nExample:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/jimlambrt/gldap\"\n)\n\nfunc main() {\n\t// create a new server\n\ts, err := gldap.NewServer()\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to create server: %s\", err.Error())\n\t}\n\n\t// create a router and add a bind handler\n\tr, err := gldap.NewMux()\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to create router: %s\", err.Error())\n\t}\n\tr.Bind(bindHandler)\n\tr.Search(searchHandler)\n\ts.Router(r)\n\tgo s.Run(\":10389\") // listen on port 10389\n\n\t// stop server gracefully when ctrl-c, sigint or sigterm occurs\n\tctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)\n\tdefer stop()\n\tselect {\n\tcase \u003c-ctx.Done():\n\t\tlog.Printf(\"\\nstopping directory\")\n\t\ts.Stop()\n\t}\n}\n\nfunc bindHandler(w *gldap.ResponseWriter, r *gldap.Request) {\n\tresp := r.NewBindResponse(\n\t\tgldap.WithResponseCode(gldap.ResultInvalidCredentials),\n\t)\n\tdefer func() {\n\t\tw.Write(resp)\n\t}()\n\n\tm, err := r.GetSimpleBindMessage()\n\tif err != nil {\n\t\tlog.Printf(\"not a simple bind message: %s\", err)\n\t\treturn\n\t}\n\n\tif m.UserName == \"alice\" {\n\t\tresp.SetResultCode(gldap.ResultSuccess)\n\t\tlog.Println(\"bind success\")\n\t\treturn\n\t}\n\nfunc searchHandler(w *gldap.ResponseWriter, r *gldap.Request) {\n\tresp := r.NewSearchDoneResponse()\n\tdefer func() {\n\t\tw.Write(resp)\n\t}()\n\tm, err := r.GetSearchMessage()\n\tif err != nil {\n\t\tlog.Printf(\"not a search message: %s\", err)\n\t\treturn\n\t}\n\tlog.Printf(\"search base dn: %s\", m.BaseDN)\n\tlog.Printf(\"search scope: %d\", m.Scope)\n\tlog.Printf(\"search filter: %s\", m.Filter)\n\n\tif strings.Contains(m.Filter, \"uid=alice\") || m.BaseDN == \"uid=alice,ou=people,cn=example,dc=org\" {\n\t\tentry := r.NewSearchResponseEntry(\n\t\t\t\"uid=alice,ou=people,cn=example,dc=org\",\n\t\t\tgldap.WithAttributes(map[string][]string{\n\t\t\t\t\"objectclass\": {\"top\", \"person\", \"organizationalPerson\", \"inetOrgPerson\"},\n\t\t\t\t\"uid\":         {\"alice\"},\n\t\t\t\t\"cn\":          {\"alice eve smith\"},\n\t\t\t\t\"givenname\":   {\"alice\"},\n\t\t\t\t\"sn\":          {\"smith\"},\n\t\t\t\t\"ou\":          {\"people\"},\n\t\t\t\t\"description\": {\"friend of Rivest, Shamir and Adleman\"},\n\t\t\t\t\"password\":    {\"{SSHA}U3waGJVC7MgXYc0YQe7xv7sSePuTP8zN\"},\n\t\t\t}),\n\t\t)\n\t\tentry.AddAttribute(\"email\", []string{\"alice@example.org\"})\n\t\tw.Write(entry)\n\t\tresp.SetResultCode(gldap.ResultSuccess)\n\t}\n\tif m.BaseDN == \"ou=people,cn=example,dc=org\" {\n\t\tentry := r.NewSearchResponseEntry(\n\t\t\t\"ou=people,cn=example,dc=org\",\n\t\t\tgldap.WithAttributes(map[string][]string{\n\t\t\t\t\"objectclass\": {\"organizationalUnit\"},\n\t\t\t\t\"ou\":          {\"people\"},\n\t\t\t}),\n\t\t)\n\t\tw.Write(entry)\n\t\tresp.SetResultCode(gldap.ResultSuccess)\n\t}\n\treturn\n}\n```\n\u003chr\u003e\n\n## Road map\n\n### Currently supported features:\n\n* `ldap`, `ldaps` and `mTLS` connections\n* StartTLS Requests\n* Bind Requests\n  * Simple Auth (user/pass) \n* Search Requests\n* Modify Requests\n* Add Requests\n* Delete Requests\n* Unbind Requests\n\n### Future features\nAt this point, we may wait until issues are opened before planning new features\ngiven that all the basic LDAP operations are supported. \n\n\u003chr\u003e\n\n## [gldap.testdirectory](testdirectory/README.md)\n[![Go\nReference](https://pkg.go.dev/badge/github.com/jimlambrt/gldap/testdirectory.svg)](https://pkg.go.dev/github.com/jimlambrt/gldap/testdirectory) \n\nThe `testdirectory` package built using `gldap` which provides an in-memory test\nLDAP service with capabilities which make writing tests that depend on an LDAP\nservice much easier.  \n\n`testdirectory` is also a great working example of how you can use `gldap` to build a custom\nldap server to meet your specific needs.\n\nExample:\n\n```go\n// this testdirectory example demonstrates how can start a test directory for \n// your unit tests which will automatically stop when the test is complete. \nfunc TestExample(t *testing.T) {\n\n\t// start a test directory running ldaps on an available free port (defaults)\n\t// that allows anon binds (a default override)\n\ttd := testdirectory.Start(t,\n\t\ttestdirectory.WithDefaults(\u0026testdirectory.Defaults{AllowAnonymousBind: true}),\n\t)\n\t// create some test new user entries (using defaults for ou, password, etc)\n\tusers := testdirectory.NewUsers(t, []string{\"alice\", \"bob\"})\n\t// set the test directories user entries\n\ttd.SetUsers(users...)\n\n\t// INSERT your tests here....\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimlambrt%2Fgldap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjimlambrt%2Fgldap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimlambrt%2Fgldap/lists"}