2022-10-08 18:49:08 +02:00
|
|
|
|
# glapi
|
|
|
|
|
|
2022-10-05 19:25:56 +02:00
|
|
|
|
Go Ldap API is an HTTP API to an LDAP backend.
|
2022-11-12 20:53:12 +01:00
|
|
|
|
Only supporting read at the moment, maybe one day it will write, and break LDAP backends with ease and joy!
|
|
|
|
|
UPDATE: Yay, the day has come!
|
2022-10-08 18:49:08 +02:00
|
|
|
|
|
2022-10-08 19:05:54 +02:00
|
|
|
|
## Usage
|
2022-10-08 18:49:08 +02:00
|
|
|
|
Start glapi with parameters on command line:
|
|
|
|
|
```
|
|
|
|
|
glapi -ldap-host ldap://ldap.example.org -ldap-base-dn dc=example,dc=org -ldap-user cn=yo,dc=example,dc=org -ldap-pass 'here_is_the_password'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
or point it to a configuration file :
|
|
|
|
|
```
|
|
|
|
|
glapi -config glapi.env
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-08 19:05:54 +02:00
|
|
|
|
## Configuration file
|
|
|
|
|
```
|
2022-11-12 14:05:53 +01:00
|
|
|
|
LISTEN="0.0.0.0:8443"
|
2022-10-08 18:49:08 +02:00
|
|
|
|
LDAP_HOST="ldap://ldap.example.org"
|
2023-08-07 14:01:04 +02:00
|
|
|
|
# The base DN exposed to API. Could be buried in LDAP tree so we expose only a subset of directory.
|
2022-10-08 18:49:08 +02:00
|
|
|
|
LDAP_BASE_DN="dc=example,dc=org"
|
2022-11-12 14:05:14 +01:00
|
|
|
|
|
|
|
|
|
# This account search for valid user provided by authenticating client.
|
|
|
|
|
# Then glapi bind with client provided credentials to operate LDAP.
|
|
|
|
|
# Thus this account only needs bind privilege, and read access to users organizational unit
|
|
|
|
|
LDAP_USER="cn=ldapreaduser,dc=example,dc=org"
|
|
|
|
|
LDAP_PASS='here_lies_the_password'
|
|
|
|
|
|
2023-08-07 14:01:04 +02:00
|
|
|
|
# This base DN is where we seach for authenticating accounts. This way we can chose not to expose them to the API.
|
|
|
|
|
LDAP_AUTH_BASE_DN="ou=users,dc=example,dc=org"
|
|
|
|
|
|
2022-11-12 14:05:14 +01:00
|
|
|
|
# Https support
|
|
|
|
|
HTTPS=true
|
|
|
|
|
SSL_CERTIFICATE=/etc/ssl/certs/server.pem
|
|
|
|
|
SSL_PRIVATE_KEY=/etc/ssl/private/server.key
|
2022-10-08 18:49:08 +02:00
|
|
|
|
```
|
|
|
|
|
|
2022-10-08 19:05:54 +02:00
|
|
|
|
## Querying API
|
2022-11-12 20:54:37 +01:00
|
|
|
|
### Search Entries
|
2022-10-08 19:05:54 +02:00
|
|
|
|
Search LDAP entries through the whole subtree, specifying organizationalUnit, commnName, objectClass, attribute to retrieve.
|
|
|
|
|
Each of these parameters can be replaced by "ALL" to act like a wildcard.
|
|
|
|
|
```
|
2022-10-08 18:49:08 +02:00
|
|
|
|
% curl -u admin:admin http://127.0.0.1:8080/ou=domains/yo/person | jq
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
"DN": "cn=yo,dc=example.org,ou=domains,dc=example,dc=org",
|
|
|
|
|
"Attributes": [
|
|
|
|
|
{
|
|
|
|
|
"Name": "sn",
|
|
|
|
|
"Values": [
|
|
|
|
|
"yo"
|
|
|
|
|
],
|
|
|
|
|
"ByteValues": [
|
|
|
|
|
"eW8="
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Name": "cn",
|
|
|
|
|
"Values": [
|
|
|
|
|
"yo"
|
|
|
|
|
],
|
|
|
|
|
"ByteValues": [
|
|
|
|
|
"eW8="
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Name": "objectClass",
|
|
|
|
|
"Values": [
|
|
|
|
|
"inetOrgPerson",
|
|
|
|
|
"organizationalPerson",
|
|
|
|
|
"person",
|
|
|
|
|
"top",
|
|
|
|
|
"inetLocalMailRecipient"
|
|
|
|
|
],
|
|
|
|
|
"ByteValues": [
|
|
|
|
|
"aW5ldE9yZ1BlcnNvbg==",
|
|
|
|
|
"b3JnYW5pemF0aW9uYWxQZXJzb24=",
|
|
|
|
|
"cGVyc29u",
|
|
|
|
|
"dG9w",
|
|
|
|
|
"aW5ldExvY2FsTWFpbFJlY2lwaWVudA=="
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Name": "mail",
|
|
|
|
|
"Values": [
|
|
|
|
|
"yo@example.org"
|
|
|
|
|
],
|
|
|
|
|
"ByteValues": [
|
|
|
|
|
"eW9AcGxvcGl0by50aw=="
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Name": "mailLocalAddress",
|
|
|
|
|
"Values": [
|
|
|
|
|
"root@example.org",
|
|
|
|
|
"postmaster@example.org",
|
|
|
|
|
],
|
|
|
|
|
"ByteValues": [
|
|
|
|
|
"cm9vdEBleGFtcGxlLm9yZw==",
|
|
|
|
|
"cG9zdG1hc3RlckBleGFtcGxlLm9yZw==",
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Name": "uid",
|
|
|
|
|
"Values": [
|
|
|
|
|
"yo"
|
|
|
|
|
],
|
|
|
|
|
"ByteValues": [
|
|
|
|
|
"eW8="
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Using wildcards everywhere and ldif format, you can get a dump of ldap:
|
|
|
|
|
```
|
|
|
|
|
% curl -u admin:admin "http://127.0.0.1:8080/ALL/ALL/ALL?format=ldif"
|
|
|
|
|
dn: dc=example,dc=org
|
|
|
|
|
objectClass: organization
|
|
|
|
|
objectClass: top
|
|
|
|
|
objectClass: dcObject
|
|
|
|
|
dc: example
|
|
|
|
|
o: example.org
|
|
|
|
|
|
|
|
|
|
dn: cn=admin,dc=example,dc=org
|
|
|
|
|
objectClass: organizationalRole
|
|
|
|
|
objectClass: top
|
|
|
|
|
objectClass: simpleSecurityObject
|
|
|
|
|
cn: admin
|
|
|
|
|
|
|
|
|
|
dn: cn=yo,dc=example,dc=org
|
|
|
|
|
objectClass: organizationalRole
|
|
|
|
|
objectClass: top
|
|
|
|
|
objectClass: simpleSecurityObject
|
|
|
|
|
cn: yo
|
|
|
|
|
userPassword: {SSHA}edited
|
|
|
|
|
|
|
|
|
|
[...]
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-08 19:05:54 +02:00
|
|
|
|
Add operational attributes with "*,+":
|
|
|
|
|
```
|
2022-10-08 18:49:08 +02:00
|
|
|
|
% curl -u admin:admin "http://127.0.0.1:8080/ALL/ALL/ALL/*,+?format=ldif"
|
|
|
|
|
dn: dc=example,dc=org
|
|
|
|
|
objectClass: organization
|
|
|
|
|
objectClass: top
|
|
|
|
|
objectClass: dcObject
|
|
|
|
|
dc: example
|
|
|
|
|
o: example.org
|
|
|
|
|
structuralObjectClass: organization
|
|
|
|
|
entryUUID: af93fd38-3139-103a-8d41-05c00494facf
|
|
|
|
|
creatorsName: cn=admin,dc=example,dc=org
|
|
|
|
|
createTimestamp: 20200523120715Z
|
|
|
|
|
entryCSN: 20200523120715.282611Z#000000#000#000000
|
|
|
|
|
modifiersName: cn=admin,dc=example,dc=org
|
|
|
|
|
modifyTimestamp: 20200523120715Z
|
|
|
|
|
entryDN: dc=example,dc=org
|
|
|
|
|
subschemaSubentry: cn=Subschema
|
|
|
|
|
hasSubordinates: TRUE
|
|
|
|
|
|
|
|
|
|
dn: cn=admin,dc=example,dc=org
|
|
|
|
|
objectClass: organizationalRole
|
|
|
|
|
objectClass: top
|
|
|
|
|
objectClass: simpleSecurityObject
|
|
|
|
|
cn: admin
|
|
|
|
|
structuralObjectClass: organizationalRole
|
|
|
|
|
entryUUID: af9a1556-3139-103a-8d42-05c00494facf
|
|
|
|
|
creatorsName: cn=admin,dc=example,dc=org
|
|
|
|
|
createTimestamp: 20200523120715Z
|
|
|
|
|
entryCSN: 20200523120715.322559Z#000000#000#000000
|
|
|
|
|
modifiersName: cn=admin,dc=example,dc=org
|
|
|
|
|
modifyTimestamp: 20200523120715Z
|
|
|
|
|
entryDN: cn=admin,dc=example,dc=org
|
|
|
|
|
subschemaSubentry: cn=Subschema
|
|
|
|
|
hasSubordinates: FALSE
|
|
|
|
|
|
|
|
|
|
[...]
|
2022-10-08 19:05:54 +02:00
|
|
|
|
```
|
2022-10-08 18:49:08 +02:00
|
|
|
|
|
2022-11-12 20:53:12 +01:00
|
|
|
|
#### Output format
|
2022-10-08 19:05:54 +02:00
|
|
|
|
Default output is in json. The following formats are supported:
|
2022-10-08 18:49:08 +02:00
|
|
|
|
- json (default)
|
|
|
|
|
- text (ini style)
|
|
|
|
|
- ldif
|
|
|
|
|
- textvalue (only attribute values are returned)
|
2022-10-08 19:05:54 +02:00
|
|
|
|
- textvalue-nodn (only attribute values, no dn, no linefeed between entries. Made for Rspamd multimap module)
|
2022-10-08 18:49:08 +02:00
|
|
|
|
|
2022-10-08 19:05:54 +02:00
|
|
|
|
Specify with "format" query parameter:
|
2022-10-08 18:49:08 +02:00
|
|
|
|
```
|
|
|
|
|
% curl -u admin:admin "http://127.0.0.1:8080/ou=domains/yo/person?format=text"
|
|
|
|
|
dn=cn=yo,dc=example.org,ou=domains,dc=example,dc=org
|
|
|
|
|
sn=yo
|
|
|
|
|
cn=yo
|
|
|
|
|
objectClass=inetOrgPerson
|
|
|
|
|
objectClass=organizationalPerson
|
|
|
|
|
objectClass=person
|
|
|
|
|
objectClass=top
|
|
|
|
|
objectClass=inetLocalMailRecipient
|
|
|
|
|
mail=yo@example.org
|
|
|
|
|
mailLocalAddress=root@example.org
|
|
|
|
|
mailLocalAddress=postmaster@example.org
|
|
|
|
|
uid=yo
|
|
|
|
|
|
|
|
|
|
% curl -u admin:admin "http://127.0.0.1:8080/ou=domains/yo/person?format=ldif"
|
|
|
|
|
dn: cn=yo,dc=example.org,ou=domains,dc=example,dc=org
|
|
|
|
|
sn: yo
|
|
|
|
|
cn: yo
|
|
|
|
|
objectClass: inetOrgPerson
|
|
|
|
|
objectClass: organizationalPerson
|
|
|
|
|
objectClass: person
|
|
|
|
|
objectClass: top
|
|
|
|
|
objectClass: inetLocalMailRecipient
|
|
|
|
|
mail: yo@example.org
|
|
|
|
|
mailLocalAddress: root@example.org
|
|
|
|
|
mailLocalAddress=postmaster@example.org
|
|
|
|
|
uid: yo
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-12 20:53:12 +01:00
|
|
|
|
#### Select attributes to get
|
2022-10-08 19:05:54 +02:00
|
|
|
|
You can select attributes to get by adding them in 4th position :
|
|
|
|
|
```
|
2022-10-08 18:49:08 +02:00
|
|
|
|
% curl -u admin:admin "http://127.0.0.1:8080/ou=domains/yo/person/mail?format=textvalue"
|
|
|
|
|
cn=yo,dc=example.org,ou=domains,dc=example,dc=org
|
|
|
|
|
yo@example.org
|
|
|
|
|
|
|
|
|
|
% curl -u admin:admin "http://127.0.0.1:8080/ou=domains/yo/person/mail?format=textvalue-nodn"
|
|
|
|
|
yo@example.org
|
|
|
|
|
```
|
2022-11-12 20:53:12 +01:00
|
|
|
|
|
|
|
|
|
### Create entries
|
|
|
|
|
Create a new OU =users", then a new user :
|
|
|
|
|
```
|
|
|
|
|
% curl -u "admin:admin" --header "Content-Type: application/json" -X POST
|
|
|
|
|
--data '{"objectClass":["organizationalUnit","top"],"ou":"users"' \
|
|
|
|
|
https://127.0.0.1:8443/ou=users,dc=example,dc=org
|
|
|
|
|
|
|
|
|
|
% curl -u "admin:admin" --header "Content-Type: application/json" -X POST
|
|
|
|
|
--data '{"objectClass":["person","top"],"cn":"newuser","sn":"New"}' \
|
|
|
|
|
https://127.0.0.1:8443/cn=newuser,ou=users,dc=example,dc=org
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Modify entries
|
|
|
|
|
Add a description to the new account:
|
|
|
|
|
```
|
|
|
|
|
% curl -u "admin:admin" --header "Content-Type: application/json" -X PUT
|
|
|
|
|
--data '{"objectClass":["person","top"],"cn":"newuser","sn":"New","description":"Test account"}' \
|
|
|
|
|
https://127.0.0.1:8443/cn=newuser,ou=users,dc=example,dc=org
|
|
|
|
|
```
|
|
|
|
|
Missing attributes will be removed from entry.
|
|
|
|
|
|
|
|
|
|
### Delete entries
|
|
|
|
|
Remove newuser :
|
|
|
|
|
```
|
|
|
|
|
% curl -u "admin:admin" -X DELETE \
|
|
|
|
|
https://127.0.0.1:8443/cn=newuser,ou=users,dc=example,dc=org
|
|
|
|
|
```
|