|
1 | 1 | # Goberus |
2 | 2 |
|
3 | | -Goberus is a minimal LDAPS middleware implementing a get_member_info endpoint for Active Directory / LDAP. |
4 | | -This repository contains a small Go service that connects to an LDAPS server, searches for a user (by userPrincipalName or sAMAccountName), and returns a JSON representation of select attributes. |
| 3 | + |
5 | 4 |
|
6 | | -This repo is intentionally minimal so you can validate functionality before we extend it further (password operations, API auth, pooling, tests, etc.). |
| 5 | +A minimal LDAP-backed service that exposes member lookup and provisioning workflows via `/v1/member`. |
7 | 6 |
|
8 | | -Status |
9 | | -- Initial implementation: GET /v1/member?username=<username> |
10 | | -- LDAPS client dials and binds per request (simple, robust for testing) |
11 | | -- TLS verification is configurable (recommended to provide a CA cert) |
| 7 | +## Status |
| 8 | +- [x] `GET /v1/member?username=<value>` — resolves a user by UPN or sAMAccountName and returns normalized attributes via `server.UserClient` backed by `ldaps.Client` in production and fakes in tests. |
| 9 | +- [x] `POST /v1/member` — sanitizes the JSON payload (trim + lowercase for `username`/`OrganizationalUnit`) with `handlers.SanitizeUser` before invoking `ldaps.Client.AddUser`. |
| 10 | +- [ ] `DELETE /v1/member` — TODO: expose member removal once LDAP delete semantics and authorization are finalized. |
| 11 | +- [ ] `PATCH /v1/member` — TODO: introduce attribute updates once LDAP modify flows are defined. |
| 12 | +- `tests/server/handlers_test.go` covers the handler flows (including an integration-style `httptest.NewServer` canary), and `handlers/users_test.go` focuses on `SanitizeUser`. |
12 | 13 |
|
13 | | -Quick start — run locally |
14 | | -1. Prerequisites |
15 | | - - Go 1.21+ |
16 | | - - Network access to your Active Directory on LDAPS (TCP 636) |
| 14 | +## Development & testing |
| 15 | +See [docs/dev-setup.md](docs/dev-setup.md) for the quick-start instructions, environment variables, Docker guidance, troubleshooting tips, and the testing commands (`go test ./tests/server -run TestHandleGetMember`, `go test ./tests/server -run TestHandleCreateMember`, `go test ./tests/server -run TestSanitizeUserIntegration`, `go test ./...`). |
17 | 16 |
|
18 | | -2. Set environment variables (example) |
19 | | -```bash |
20 | | -export BIND_ADDR="8080" |
21 | | -export LDAP_ADDR="ad.example.local:636" # host:port for LDAPS |
22 | | -export LDAP_BASE_DN="DC=example,DC=local" |
23 | | -export LDAP_BIND_DN="CN=svc-goberus,OU=svc,DC=example,DC=local" |
24 | | -export LDAP_BIND_PASSWORD="supersecret" |
25 | | -export LDAP_SKIP_VERIFY="false" # set true only for dev testing |
26 | | -# Or better: provide CA cert that signed the AD server cert: |
27 | | -# export LDAP_CA_CERT="/path/to/ca.pem" |
28 | | -``` |
29 | | - |
30 | | -3. Build and run |
31 | | -```bash |
32 | | -go mod tidy |
33 | | -go build -o goberus ./... |
34 | | -./goberus |
35 | | -``` |
36 | | - |
37 | | -4. Query the service |
38 | | -```bash |
39 | | -curl 'http://localhost:8080/v1/member?username=jdoe' | jq . |
40 | | -# or with UPN: |
41 | | -curl 'http://localhost:8080/v1/member?username=jdoe@example.local' | jq . |
42 | | -``` |
43 | | - |
44 | | -Docker — build and run |
45 | | -A multi-stage Dockerfile is provided to build a small runtime image. |
46 | | - |
47 | | -Build: |
48 | | -```bash |
49 | | -docker build -t lugatuic/goberus:latest . |
50 | | -``` |
51 | | - |
52 | | -Run (example): |
53 | | -```bash |
54 | | -docker run --rm -p 8080:8080 \ |
55 | | - -e BIND_ADDR=":8080" \ |
56 | | - -e LDAP_ADDR="ad.example.local:636" \ |
57 | | - -e LDAP_BASE_DN="DC=example,DC=local" \ |
58 | | - -e LDAP_BIND_DN="CN=svc-goberus,OU=svc,DC=example,DC=local" \ |
59 | | - -e LDAP_BIND_PASSWORD="supersecret" \ |
60 | | - -e LDAP_SKIP_VERIFY="false" \ |
61 | | - lugatuic/goberus:latest |
62 | | -``` |
63 | | - |
64 | | -If you need to provide a CA certificate file to verify the LDAPS server certificate, mount it into the container and set `LDAP_CA_CERT` to the path inside the container: |
65 | | -```bash |
66 | | -docker run --rm -p 8080:8080 \ |
67 | | - -v /local/path/ca.pem:/etc/ssl/certs/goberus-ca.pem:ro \ |
68 | | - -e LDAP_CA_CERT="/etc/ssl/certs/goberus-ca.pem" \ |
69 | | - ... lugatuic/goberus:latest |
70 | | -``` |
71 | | - |
72 | | -CI tip — bake CA into the image from a secret (GitHub Actions example) |
73 | | -If you store your CA PEM as a repository secret (recommended for private/internal CAs), write it to `ad_chain.pem` in the workflow and build the image. The `Dockerfile` will copy `ad_chain.pem` into `/etc/ssl/certs/goberus-ca.pem` and set `LDAP_CA_CERT`. |
74 | | - |
75 | | -Example GitHub Actions step (assumes secret name GOBERUS_CA_PEM): |
76 | | - |
77 | | -```yaml |
78 | | -- name: Build image (write CA from secret) |
79 | | - run: | |
80 | | - echo "$GOBERUS_CA_PEM" > ad_chain.pem |
81 | | - docker build --build-arg TARGETARCH=amd64 --build-arg TARGETOS=linux -t lugatuic/goberus:latest . |
82 | | - env: |
83 | | - GOBERUS_CA_PEM: ${{ secrets.GOBERUS_CA_PEM }} |
84 | | -``` |
85 | | -
|
86 | | -Notes: |
87 | | -- Do NOT commit `ad_chain.pem` to the repository — it's added to `.gitignore` by default. |
88 | | -- The workflow writes the secret to a file only during the run and uses it to create the image. This keeps the private CA material out of the repo while allowing the image to include the CA at build time. |
89 | | -- If you prefer not to bake the CA into the image, mount it at runtime instead (see example above). |
90 | | - |
91 | | -Environment variables reference |
92 | | -- BIND_ADDR — HTTP listen address (default `:8080`) |
93 | | -- LDAP_ADDR — LDAPS address, host:port (required) |
94 | | -- LDAP_BASE_DN — base DN for searches (required) |
95 | | -- LDAP_BIND_DN — optional service DN used for searches/modify (recommended) |
96 | | -- LDAP_BIND_PASSWORD — password for LDAP_BIND_DN |
97 | | -- LDAP_SKIP_VERIFY — "true" to skip TLS verification (development only) |
98 | | -- LDAP_CA_CERT — path to CA PEM file used to verify the LDAPS server cert |
99 | | - |
100 | | -Behavior & notes |
101 | | -- Authentication: the service currently implements bind-as-user for authentication in the original design; the only exposed endpoint initially is a read/search endpoint (`/v1/member`). We will add API auth (JWT/API keys) later. |
102 | | -- Active Directory specifics: setting/changing passwords in AD requires LDAPS and AD's unicodePwd behavior (UTF-16LE quoted string). That is not implemented yet. |
103 | | -- TLS: for production, do not use `LDAP_SKIP_VERIFY=true`. Provide a CA via `LDAP_CA_CERT` or ensure the directory's cert chains to a trusted root in the container. |
104 | | - |
105 | | -Troubleshooting |
106 | | -- "x509: certificate signed by unknown authority": provide LDAP_CA_CERT or ensure the CA is installed/trusted. |
107 | | -- "Bind failed": ensure LDAP_BIND_DN is a full DN and the password is correct; try a manual ldapsearch to validate credentials. |
108 | | -- No entries found: check LDAP_BASE_DN is correct and try searching by different username formats (sAMAccountName and UPN). |
109 | | - |
110 | | -Next steps (after you verify this works) |
| 17 | +## Next steps |
111 | 18 | - Add API authentication and rate limiting |
112 | 19 | - Implement connection pooling/reconnect semantics |
113 | | -- Implement AD-safe password set/change (unicodePwd handling over LDAPS) |
114 | | -- Add unit tests + integration tests (Docker-compose with Samba AD) |
| 20 | +- Handle LDAPS password changes via `unicodePwd` |
| 21 | +- Expand unit/integration coverage (e.g., Docker-compose with Samba AD) |
115 | 22 |
|
116 | | -License |
117 | | -- Add your preferred license; none is included by default. |
| 23 | +## License |
| 24 | +Goberus is open-source software distributed under the terms of the [GNU General Public License v3](LICENSE). See `LICENSE` for the full text and warranty disclaimer. |
0 commit comments