panic 'runtime error: index out of range [0] with length 0' while prepare db record from LDAP search query when trying ldap login
I got 2022/09/08 16:14:43 http: panic serving 127.0.0.1:37156: runtime error: index out of range [0] with length 0
when logging in with LDAP credentials.
Semaphore is running as backend with a haproxy frontend
semaphore version: v2.8.65
bin/semaphore server --config /home/flybyray/git/github.com/ansible-semaphore/semaphore/.config/config.json
MySQL [email protected]:3306 semaphore
Tmp Path (projects home) /var/lib/semaphore
Semaphore v2.8.65
Interface
Port :3000
Server is running
2022/09/08 16:14:43 http: panic serving 127.0.0.1:37156: runtime error: index out of range [0] with length 0
goroutine 71 [running]:
net/http.(*conn).serve.func1()
/usr/lib/golang/src/net/http/server.go:1825 +0xbf
panic({0x9b7aa0, 0xc00002a930})
/usr/lib/golang/src/runtime/panic.go:844 +0x258
github.com/ansible-semaphore/semaphore/api.tryFindLDAPUser({0xc00002a438, 0x13}, {0xc00002c880, 0xc})
/home/flybyray/git/github.com/ansible-semaphore/semaphore/api/login.go:88 +0xfb9
github.com/ansible-semaphore/semaphore/api.login({0x1fd69a0, 0xc00014c1c0}, 0xc0008a1340?)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/api/login.go:157 +0xeb
net/http.HandlerFunc.ServeHTTP(0x9a9a20?, {0x1fd69a0?, 0xc00014c1c0?}, 0xc?)
/usr/lib/golang/src/net/http/server.go:2084 +0x2f
github.com/ansible-semaphore/semaphore/api.JSONMiddleware.func1({0x1fd69a0, 0xc00014c1c0}, 0xc0004dd750?)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/api/router.go:23 +0xf4
net/http.HandlerFunc.ServeHTTP(0xc001f60f00?, {0x1fd69a0?, 0xc00014c1c0?}, 0x98f960?)
/usr/lib/golang/src/net/http/server.go:2084 +0x2f
github.com/ansible-semaphore/semaphore/cli/cmd.runService.func1.1({0x1fd69a0, 0xc00014c1c0}, 0xc0004dd778?)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/cli/cmd/root.go:81 +0x124
net/http.HandlerFunc.ServeHTTP(0x7fb37ada65b8?, {0x1fd69a0?, 0xc00014c1c0?}, 0xc000798630?)
/usr/lib/golang/src/net/http/server.go:2084 +0x2f
github.com/gorilla/mux.CORSMethodMiddleware.func1.1({0x1fd69a0, 0xc00014c1c0}, 0xc0001dc7b0?)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/vendor/github.com/gorilla/mux/middleware.go:51 +0xaa
net/http.HandlerFunc.ServeHTTP(0xc001f60e00?, {0x1fd69a0?, 0xc00014c1c0?}, 0x9d8760?)
/usr/lib/golang/src/net/http/server.go:2084 +0x2f
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0002c2000, {0x1fd69a0, 0xc00014c1c0}, 0xc001f60d00)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/vendor/github.com/gorilla/mux/mux.go:212 +0x202
github.com/gorilla/handlers.ProxyHeaders.func1({0x1fd69a0, 0xc00014c1c0}, 0xc001f60d00)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/vendor/github.com/gorilla/handlers/proxy_headers.go:59 +0x142
net/http.HandlerFunc.ServeHTTP(0x3b?, {0x1fd69a0?, 0xc00014c1c0?}, 0x0?)
/usr/lib/golang/src/net/http/server.go:2084 +0x2f
github.com/ansible-semaphore/semaphore/cli/cmd.cropTrailingSlashMiddleware.func1({0x1fd69a0?, 0xc00014c1c0?}, 0xc001f60d00?)
/home/flybyray/git/github.com/ansible-semaphore/semaphore/cli/cmd/server.go:27 +0xf7
net/http.HandlerFunc.ServeHTTP(0x0?, {0x1fd69a0?, 0xc00014c1c0?}, 0x413885?)
/usr/lib/golang/src/net/http/server.go:2084 +0x2f
net/http.serverHandler.ServeHTTP({0x1fd4eb0?}, {0x1fd69a0, 0xc00014c1c0}, 0xc001f60d00)
/usr/lib/golang/src/net/http/server.go:2916 +0x43b
net/http.(*conn).serve(0xc000620320, {0x1fd6d78, 0xc0004d7c80})
/usr/lib/golang/src/net/http/server.go:1966 +0x5d7
created by net/http.(*Server).Serve
/usr/lib/golang/src/net/http/server.go:3071 +0x4db
It looks like sr.Entries[0] has no Entries at all ( at https://github.com/ansible-semaphore/semaphore/blob/v2.8.65/api/login.go#L88 ).
The config.json
{
"mysql": {
"host": "10.0.0.14:3306",
...
},
...
"dialect": "mysql",
...
"ldap_binddn": "uid=LDAP_BINDING_USER,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com",
"ldap_bindpassword": "LDAP_BINDING_PASSWORD",
"ldap_server": "ldap.jumpcloud.com:636",
"ldap_searchdn": "ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com",
"ldap_searchfilter": "(&(objectClass=inetOrgPerson)(memberOf=cn=a0-admin-ansible-semaphore-test,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com)(uid=%s))",
"ldap_mappings": {
"dn": "dn",
"mail": "mail",
"uid": "uid",
"cn": "cn"
},
...
"ldap_enable": true,
"ldap_needtls": true,
...
"demo_mode": false
}
The corresponding ldapsearch query /bin/ldapsearch -H ldaps://ldap.jumpcloud.com:636 -x -b "ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com" -D "uid=LDAP_BINDING_USER,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com" -W "(&(objectClass=inetOrgPerson)(memberOf=cn=a0-admin-ansible-semaphore-test,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com))"
results:
# extended LDIF
#
# LDAPv3
# base <ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com> with scope subtree
# filter: (&(objectClass=inetOrgPerson)(memberOf=cn=a0-admin-ansible-semaphore-test,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com))
# requesting: ALL
#
# admin.flybyray, Users, YOUR_ORG_ID, jumpcloud.com
dn: uid=admin.flybyray,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com
...
mail: [email protected]
...
cn: Admin Robert Rettig
...
uid: admin.flybyray
...
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 4
Ref:
- https://support.jumpcloud.com/support/s/article/using-jumpclouds-ldap-as-a-service1
- https://support.jumpcloud.com/support/s/article/using-ldapsearch-with-jumpcloud1
Further investigation reveals that the current implementation assumes that the login user has additional LDAP permissions.
https://github.com/ansible-semaphore/semaphore/blob/v2.8.65/api/login.go#L67-L71
With JumpCloud there is a additional flag with the description Allows user to bind to and search the JumpCloud LDAP service.

It would be better to use whoami operation.
see man ldapwhoami
ldapwhoami opens a connection to an LDAP server, binds, and performs a whoami operation.
https://github.com/go-ldap/ldap/blob/v3.4.4/whoami.go https://github.com/go-ldap/ldap/blob/v3.4.4/v3/examples_test.go#L396-L416
There is a special command to "Testing Client Authentication"
/bin/ldapwhoami\
-H ldaps://ldap.jumpcloud.com:636\
-D "uid=admin.flybyray,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com"\
-x\
-W
Enter LDAP Password:
dn:uid=admin.flybyray,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com
$ echo $?
0
see reference https://support.jumpcloud.com/support/s/article/using-ldapsearch-with-jumpcloud1