{"id":24807340,"url":"https://github.com/sarumaj/ldap-cli","last_synced_at":"2026-03-06T02:05:25.909Z","repository":{"id":206077972,"uuid":"703588262","full_name":"sarumaj/ldap-cli","owner":"sarumaj","description":"Cross-platform compatible LDAP-based command-line interface","archived":false,"fork":false,"pushed_at":"2026-02-03T17:51:01.000Z","size":8588,"stargazers_count":5,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-04T07:16:17.249Z","etag":null,"topics":["cli","directory-services","ldap"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/sarumaj/ldap-cli/v2","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/sarumaj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["sarumaj"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["paypal.me/danviddo"],"buy_me_a_coffee":"sarumaj"}},"created_at":"2023-10-11T14:19:17.000Z","updated_at":"2025-12-25T13:37:40.000Z","dependencies_parsed_at":"2023-11-10T20:26:39.383Z","dependency_job_id":"a9005e95-b996-4d80-b6cb-b643eea19c2a","html_url":"https://github.com/sarumaj/ldap-cli","commit_stats":null,"previous_names":["sarumaj/ldap-cli"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/sarumaj/ldap-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sarumaj%2Fldap-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sarumaj%2Fldap-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sarumaj%2Fldap-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sarumaj%2Fldap-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sarumaj","download_url":"https://codeload.github.com/sarumaj/ldap-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sarumaj%2Fldap-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30158903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T22:39:40.138Z","status":"online","status_checked_at":"2026-03-06T02:00:08.268Z","response_time":250,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cli","directory-services","ldap"],"created_at":"2025-01-30T09:18:23.361Z","updated_at":"2026-03-06T02:05:25.885Z","avatar_url":"https://github.com/sarumaj.png","language":"Go","funding_links":["https://github.com/sponsors/sarumaj","paypal.me/danviddo","https://buymeacoffee.com/sarumaj"],"categories":[],"sub_categories":[],"readme":"[![test_and_report](https://github.com/sarumaj/ldap-cli/actions/workflows/test_and_report.yml/badge.svg)](https://github.com/sarumaj/ldap-cli/actions/workflows/test_and_report.yml)\n[![build_and_release](https://github.com/sarumaj/ldap-cli/actions/workflows/build_and_release.yml/badge.svg)](https://github.com/sarumaj/ldap-cli/actions/workflows/build_and_release.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/sarumaj/ldap-cli)](https://goreportcard.com/report/github.com/sarumaj/ldap-cli)\n[![Maintainability](https://qlty.sh/gh/sarumaj/projects/ldap-cli/maintainability.svg)](https://qlty.sh/gh/sarumaj/projects/ldap-cli)\n[![Code Coverage](https://qlty.sh/gh/sarumaj/projects/ldap-cli/coverage.svg)](https://qlty.sh/gh/sarumaj/projects/ldap-cli)\n[![Go Reference](https://pkg.go.dev/badge/github.com/sarumaj/ldap-cli/v2.svg)](https://pkg.go.dev/github.com/sarumaj/ldap-cli/v2)\n[![Go version](https://img.shields.io/github/go-mod/go-version/sarumaj/ldap-cli?logo=go\u0026label=\u0026labelColor=gray)](https://go.dev)\n[![Release](https://img.shields.io/github/v/release/sarumaj/ldap-cli?logo=github)](https://github.com/sarumaj/ldap-cli/releases/latest)\n[![Release Date](https://img.shields.io/github/release-date/sarumaj/ldap-cli?logo=github)](https://github.com/sarumaj/ldap-cli/releases/latest)\n[![Commits since latest release](https://img.shields.io/github/commits-since/sarumaj/ldap-cli/latest?logo=github)](https://github.com/sarumaj/ldap-cli/releases/latest)\n[![Downloads (all assets, all releases)](https://img.shields.io/github/downloads/sarumaj/ldap-cli/total?logo=github)](https://github.com/sarumaj/ldap-cli/releases)\n[![Downloads (all assets, latest release)](https://img.shields.io/github/downloads/sarumaj/ldap-cli/latest/total?logo=github)](https://github.com/sarumaj/ldap-cli/releases/latest)\n\n---\n\n# ldap-cli\n\n**ldap-cli** is a cross-platform compatible LDAP-based command-line interface allowing ETL operations on Directory objects using LDAP Data Interchange Format (LDIF).\n\nThe CLI application is written in Go and uses the Cobra framework.\nIt is mainly intended for administrators and developers who want to query and edit directory objects.\nIt is highly adopted to work with Microsoft Active Directory, although openldap implementations are being used for testing.\n\nDeveloped as Computer Science Project for IU ([www.iu-fernstudium.de](https://iu-fernstudium.de)).\n\n## Installation\n\nDownload executable binary from the [release section](https://github.com/sarumaj/ldap-cli/releases/latest), e.g.:\n\n```console\n$ latest=$(curl -fsSI https://github.com/sarumaj/ldap-cli/releases/latest | grep -i location | sed 's/\\r$//' | awk -F/ '{print $NF}') \u0026\u0026 \\\n  curl -fsSL \"https://github.com/sarumaj/ldap-cli/releases/download/${latest}/ldap-cli_${latest}_linux-amd64\" -o /usr/local/bin/ldap-cli\n$ chmod +x /usr/local/bin/ldap-cli\n```\n\nAlternatively, build from source code (requires go 1.21.x runtime):\n\n```console\n$ git clone https://github.com/sarumaj/ldap-cli\n$ cd ldap-cli\n$ go build \\\n    -trimpath \\\n    -ldflags=\"-s -w -X 'main.Version=$(git describe --tags $(git rev-list --tags --max-count=1))' -X 'main.BuildDate=$(date -u \"+%Y-%m-%d %H:%M:%S UTC\")' -extldflags=-static\" \\\n    -tags=\"osusergo netgo static_build\" \\\n    -o /usr/local/bin/ldap-cli \\\n    \"cmd/ldap-cli/main.go\"\n$ chmod +x /usr/local/bin/ldap-cli\n```\n\n## Features\n\n- [x] LDAP/LDAPS authentication\n  - [x] SIMPLE BIND\n  - [x] NTLM (**not tested**)\n  - [x] UNAUTHENTICATED\n  - [x] MD5 (**not tested**)\n  - [ ] ~~GSSAPI SASL~~ (**not supported**)\n  - [x] Preserve credentials in a keyring\n- [x] Search directory objects\n  - [x] Track progress of search operations\n  - [x] Search users with options (user-id, enabled, expired, memberOf)\n  - [x] Search groups with options (group-id)\n  - [x] Search by providing custom LDAP filter\n    - [x] Parse and validate filter syntax\n    - [x] Register lexical aliases\n- [x] Edit directory objects\n  - [x] Edit group members\n    - [x] Support arbitrary membership attribute\n    - [x] LDIF edit mode\n  - [x] Edit user's password\n    - [x] Support arbitrary password attribute\n    - [ ] ~~Option to pass old password~~ (**not supported**)\n    - [x] LDIF edit mode\n  - [x] Edit custom objects\n    - [x] LDIF edit mode\n- [x] Interactive mode operandi\n  - [x] Ask for inputs\n  - [x] Utilize ANSI code sequences if available\n- [x] Support multiple output formats (CSV, LDIF, YAML)\n- [x] Custom filter syntax\n\n## TODO\n\n- [ ] Implement LDAP Password Modify Extended Operation\n- [ ] Test interactive UI\n- [ ] Support AD object creation\n- [ ] Support AD object disposal\n\n## Usage\n\n### Command line interface\n\nRun `ldap-cli --help` to retrieve help on usage.\n\n```console\n$ ldap-cli --help\n\n\u003e ldap-cli is cross-platform compatible client application based on the lightweight directory access control (LDAP)\n\u003e\n\u003e Usage:\n\u003e   ldap-cli [flags]\n\u003e   ldap-cli [command]\n\u003e\n\u003e Examples:\n\u003e ldap-cli --user \"DOMAIN\\\\user\" --password \"password\" --url \"ldaps://example.com:636\" \u003ccommand\u003e\n\u003e\n\u003e Available Commands:\n\u003e   completion  Generate the autocompletion script for the specified shell\n\u003e   edit        Edit a directory object\n\u003e   get         Get a directory object\n\u003e   help        Help about any command\n\u003e   version     Display version information\n\u003e\n\u003e Flags:\n\u003e       --auth-type string   Set authentication schema (supported: [\"MD5\", \"NTLM\", \"SIMPLE\", \"UNAUTHENTICATED\"]) (default \"UNAUTHENTICATED\")\n\u003e   -v, --debug              Set log level to debug (-v for verbose, -vv for trace)\n\u003e       --disable-tls        Disable TLS (not recommended)\n\u003e       --domain string      Set domain (required for NTLM authentication schema)\n\u003e   -h, --help               help for ldap-cli\n\u003e       --max-retries uint   Specify number of retries (default 3)\n\u003e       --password string    Set password (will be ignored if authentication schema is set to UNAUTHENTICATED)\n\u003e       --size-limit int     Specify query size limit (-1: unlimited) (default 2000)\n\u003e       --timeout duration   Specify query timeout (default 10m0s)\n\u003e       --url string         Provide address of the directory server (default \"ldap://localhost:389\")\n\u003e       --user string        Set username (will be ignored if authentication schema is set to UNAUTHENTICATED)\n\u003e\n\u003e Use \"ldap-cli [command] --help\" for more information about a command.\n```\n\n### Custom filter syntax\n\nE.g. following filter expression:\n\n```\n$AND($USER; $MEMBER_OF(CN=LocalUsers,DC=example,DC=com; true); $NOT($MEMBER_OF(CN=Employers,DC=example,DC=com; true)))\n```\n\ncorresponds with the following LDAP filter expression:\n\n```\n(\u0026\n  (|\n    (ObjectClass=user)\n    (ObjectClass=posixAccount)\n  )\n  (MemberOf:1.2.840.113556.1.4.1941:=CN=LocalUsers,DC=example,DC=com)\n  (!\n    (MemberOf:1.2.840.113556.1.4.1941:=CN=Employers,DC=example,DC=com)\n  )\n)\n```\n\nFollowing expressions are supported:\n\n| Filter expression                                   | Corresponding LDAP filter expression                                                                                                            |\n| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| `$ATTR(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?operator\u003e; \u003c?rule\u003e)` | `(\u003cattribute\u003e:\u003c?rule\u003e:\u003c?operator\u003e\u003cvalue\u003e)`                                                                                                      |\n| `$CONTAINS(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`          | `(\u003cattribute\u003e:\u003c?rule\u003e:=*\u003cvalue\u003e*)`                                                                                                              |\n| `$ENDS_WITH(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`         | `(\u003cattribute\u003e:\u003c?rule\u003e:=*\u003cvalue\u003e)`                                                                                                               |\n| `$BAND`                                             | `1.2.840.113556.1.4.803`                                                                                                                        |\n| `$BOR`                                              | `1.2.840.113556.1.4.804`                                                                                                                        |\n| `$DATA`                                             | `1.2.840.113556.1.4.2253`                                                                                                                       |\n| `$RECURSIVE`                                        | `1.2.840.113556.1.4.1941`                                                                                                                       |\n| `$AND((filter1); ...; (filterN))`                   | `(\u0026(filter1)...(filterN))`                                                                                                                      |\n| `$NOT((filter))`                                    | `(!(filter))`                                                                                                                                   |\n| `$OR((filter1); ...; (filterN))`                    | `(\\|(filter1)...(filterN))`                                                                                                                     |\n| `$DC`                                               | `(\u0026(ObjectClass=computer)(UserAccountControl:1.2.840.113556.1.4.803:=8192))`                                                                    |\n| `$DISABLED`                                         | `(UserAccountControl:1.2.840.113556.1.4.803:=2)`                                                                                                |\n| `$ENABLED`                                          | `(!(UserAccountControl:1.2.840.113556.1.4.803:=2))`                                                                                             |\n| `$EQ(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`                | `(\u003cattribute\u003e:\u003c?rule\u003e:=\u003cvalue\u003e)`                                                                                                                |\n| `$EXISTS(\u003cattribute\u003e)`                              | `(\u003cattribute\u003e=*)`                                                                                                                               |\n| `$EXPIRED`                                          | `(\u0026(AccountExpires=\u003e0)(AccountExpires=\u003c9223372036854775807)(AccountExpires=\u003c92233720368547758)(AccountExpires=*))`                              |\n| `$GROUP`                                            | `(\\|(ObjectClass=group)(ObjectClass=posixGroup))`                                                                                               |\n| `$GT(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`                | `(\u003cattribute\u003e:\u003c?rule\u003e:=\u003e\u003cvalue\u003e)`                                                                                                               |\n| `$GTE(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`               | `(\u003cattribute\u003e:\u003c?rule\u003e:\u003e=\u003cvalue\u003e)`                                                                                                               |\n| `$ID(\u003cid\u003e)`                                         | `(\\|(CN=\u003cid\u003e)(DisplayName=\u003cid\u003e)(\\|(DistinguishedName=\u003cid\u003e)(DN=\u003cid\u003e))(Name=\u003cid\u003e)(SAMAccountName=\u003cid\u003e)(UserPrincipalName=\u003cid\u003e)(ObjectGuid=\u003cid\u003e))` |\n| `$LIKE(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`              | `(\u003cattribute\u003e:\u003c?rule\u003e:~=\u003cvalue\u003e)`                                                                                                               |\n| `$LT(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`                | `(\u003cattribute\u003e:\u003c?rule\u003e:=\u003c\u003cvalue\u003e)`                                                                                                               |\n| `$LTE(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`               | `(\u003cattribute\u003e:\u003c?rule\u003e:\u003c=\u003cvalue\u003e)`                                                                                                               |\n| `$MEMBER_OF(\u003cdn\u003e; \u003c?recurse\u003e)`                      | `(MemberOf=\u003cdn\u003e)`                                                                                                                               |\n| `$NOT_EXISTS(\u003cattribute\u003e)`                          | `(!(\u003cattribute\u003e=*))`                                                                                                                            |\n| `$NOT_EXPIRED`                                      | `(!(\u0026(AccountExpires=\u003e0)(AccountExpires=\u003c9223372036854775807)(AccountExpires=\u003c92233720368547758)(AccountExpires=*)))`                           |\n| `$STARTS_WITH(\u003cattribute\u003e; \u003cvalue\u003e; \u003c?rule\u003e)`       | `(\u003cattribute\u003e:\u003c?rule\u003e:=\u003cvalue\u003e*)`                                                                                                               |\n| `$USER`                                             | `(\\|(ObjectClass=user)(ObjectClass=posixAccount))`                                                                                              |\n\nParameters beginning with a question mark are optional.\n\n### Use cases\n\n#### Object retrieval\n\nFind any object:\n\n```console\n$ ldap-cli \\\n  --auth-type \"SIMPLE\" \\\n  --user \"secretuser\" \\\n  --password \"secretpassword\" \\\n  --url \"ldaps://example.com:636\" \\\n  --size-limit \"-1\" \\\n  get \\\n    --format \"ldif\" \\\n    --path \"DC=sales,DC=example,DC=com\" \\\n    --select \"dn\" \\\n  custom \\\n    --filter '$AND($USER; $ID(12345))'\n\n\u003e distinguishedName: CN=Mustermann Max (12345),OU=Users,DC=example,DC=com\n```\n\nReuse credentials from keyring and find a group object:\n\n```console\n$ ldap-cli \\\n  --url \"ldaps://example.com:636\" \\\n  --size-limit \"-1\" \\\n  get \\\n    --format \"ldif\" \\\n    --path \"DC=customers,DC=example,DC=com\" \\\n    --select \"members\" \\\n  group \\\n    --group-id \"business_sector_01\"\n\n\u003e member: CN=Mustermann Uwe (12346),OU=Users,DC=example,DC=com\n\u003e member: CN=Musterfrau Ulrike (12347),OU=Users,DC=example,DC=com\n```\n\n#### Object alternation\n\nReuse credentials from keyring and add group member:\n\n```console\n$ ldap-cli \\\n  --url \"ldaps://example.com:636\" \\\n  --size-limit \"-1\" \\\n  edit \\\n    --path \"DC=customers,DC=example,DC=com\" \\\n  group \\\n    --group-id \"business_sector_01\" \\\n    --add-member \"CN=Mustermann Max (12345),OU=Users,DC=example,DC=com\"\n\n\u003e Successfully applied modifications\n```\n\n#### Interactive UI Demonstration\n\n[![ldap-cli demo](doc/screenshot.png)](https://youtu.be/Lr1pnHph24s)\n\n### Testing\n\nAn openldap server can be used to run tests against:\n\n```console\n$ git clone https://github.com/sarumaj/ldap-cli\n$ cd ldap-cli/oat\n$ docker compose up\n$ cd ..\n$ TEST_OAT=\"true\" go test -v ./...\n```\n\n### Software Architecture\n\n```mermaid\n%%{init: { \"flowchart\": { \"htmlLabels\": true } } }%%\ngraph TB\n    CLI_Tool[\"\u003cb\u003eLDAP CLI Tool\u003c/b\u003e\"] --\u003e|Program entry point executor| Main[\"\u003cb\u003emain Package\u003c/b\u003e\"]\n    Main --\u003e|CLI command \u0026 flag definitions| App\n    App --\u003e|Authentication schemes| Auth\n    App --\u003e|Search \u0026 modify request operations| Client\n    Client --\u003e|Bind requests| Auth\n    Client --\u003e|Directory object properties| Attributes\n    App --\u003e|Directory object properties| Attributes\n    App --\u003e|Parser, schema validation \u0026 custom filter syntax| Filter\n    App --\u003e|Use| UtilLib\n    Commands --\u003e|Use| UtilApp\n    EditCustom ~~~ EditGroup\n    EditGroup ~~~ EditUser\n    GetCustom ~~~ GetGroup\n    GetGroup ~~~ GetUser\n    subgraph Lib[\"\u003cb\u003elib Package\u003c/b\u003e\"]\n        Auth[\"\u003cb\u003eauth Package\u003c/b\u003e\"]\n        Client[\"\u003cb\u003eclient Package\u003c/b\u003e\"]\n        subgraph Definitions[\"\u003cb\u003edefinitions Package\u003c/b\u003e\"]\n            Attributes[\"\n                \u003cb\u003eattributes Package\u003c/b\u003e\n\n                common attribute definitions \u0026 parsers,\n                group type definitions,\n                user account type definitions,\n                user control definitions,\n                extensible match rules\n            \"]\n            Filter[\"\n                \u003cb\u003efilter Package\u003c/b\u003e\n\n                filter implementations,\n                filter parsing,\n                custom filter syntax\n            \"]\n        end\n        UtilLib[\"\n            \u003cb\u003eutil Package\u003c/b\u003e\n\n            error definitions,\n            GUID generation,\n            hex code conversion,\n            keyring interfaces,\n            DNS resolving,\n            custom CSV reader,\n            test utilities,\n            text case alignment,\n            time-base-oriented parsing,\n            validating user input\n        \"]\n    end\n    subgraph App[\"\u003cb\u003eapp Package\u003c/b\u003e\"]\n      subgraph Internal[\"\u003cb\u003einternal Package\u003c/b\u003e\"]\n          subgraph Commands[\"\u003cb\u003ecommands Package\u003c/b\u003e\"]\n              subgraph EditCmd[\"\u003cb\u003eedit command\u003c/b\u003e\"]\n                  direction TB\n                  EditCustom[\"\n                      \u003cb\u003ecustom sub-command\u003c/b\u003e\n\n                      modify any object\n                  \"]\n                  EditGroup[\"\n                      \u003cb\u003egroup sub-command\u003c/b\u003e\n\n                      modify group object\n                  \"]\n                  EditUser[\"\n                      \u003cb\u003euser sub-command\u003c/b\u003e\n\n                      modify user object\n                  \"]\n              end\n              subgraph GetCmd[\"get command\"]\n                  direction TB\n                  GetCustom[\"\n                      \u003cb\u003ecustom sub-command\u003c/b\u003e\n\n                      query any object\n                  \"]\n                  GetGroup[\"\n                      \u003cb\u003egroup sub-command\u003c/b\u003e\n\n                      query group objects\n                  \"]\n                  GetUser[\"\n                      \u003cb\u003euser sub-command\u003c/b\u003e\n\n                      query user objects\n                  \"]\n              end\n              VersionCmd[\"\n                  \u003cb\u003eversion command\u003c/b\u003e\n\n                  verify app version,\n                  update to the latest\n              \"]\n          end\n          UtilApp[\"\n              \u003cb\u003eutil Package\u003c/b\u003e\n\n              console utils,\n              input/output format definitions,\n              command help annotations,\n              logging middleware,\n              user interactive interfaces\n          \"]\n      end\n    end\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsarumaj%2Fldap-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsarumaj%2Fldap-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsarumaj%2Fldap-cli/lists"}