Skip to content

Commit fdbb675

Browse files
authored
Create documentation to authenticate with LDAP (cvat-ai#39)
1 parent fbcf758 commit fdbb675

File tree

3 files changed

+213
-0
lines changed

3 files changed

+213
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ yarn-error.log*
4444
/site/resources/
4545
/site/node_modules/
4646
/site/tech-doc-hugo
47+
/site/.hugo_build.lock
4748

4849
# Ignore all the installed packages
4950
node_modules

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
- Tests for import/export annotation, dataset, backup from/to cloud storage
1919
- Added Python SDK package (`cvat-sdk`)
2020
- Previews for jobs
21+
- Documentation for LDAP authentication (<https://github.com/cvat-ai/cvat/pull/39>)
2122

2223
### Changed
2324
- Bumped nuclio version to 1.8.14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<!--lint disable maximum-heading-length-->
2+
3+
---
4+
5+
title: 'LDAP Backed Authentication'
6+
linkTitle: 'LDAP Login'
7+
weight: 5
8+
description: 'Allow users to login with credentials from a central source'
9+
10+
---
11+
12+
<!--lint disable maximum-line-length-->
13+
14+
### The creation of `settings.py`
15+
When integrating LDAP login, we need to create an overlay to the default CVAT
16+
settings located in
17+
[cvat/settings/production.py](https://github.com/cvat-ai/cvat/blob/develop/cvat/settings/production.py).
18+
This overlay is where we will configure Django to connect to the LDAP server.
19+
20+
The main issue with using LDAP is that different LDAP implementations have
21+
different parameters. So the options used for Active Directory backed
22+
authentication will differ if you were to be using FreeIPA.
23+
24+
### Update `docker-compose.override.yml`
25+
26+
In your override config you need to passthrough your settings and tell CVAT to
27+
use them by setting the `DJANGO_SETTINGS_MODULE` variable.
28+
29+
```yml
30+
version: '3.3'
31+
32+
services:
33+
cvat:
34+
environment:
35+
DJANGO_SETTINGS_MODULE: settings
36+
volumes:
37+
- ./settings.py:/home/django/settings.py:ro
38+
```
39+
40+
### Active Directory Example
41+
42+
The following example should allow for users to authenticate themselves against
43+
Active Directory. This example requires a dummy user named `cvat_bind`. The
44+
configuration for the bind account does not need any special permissions.
45+
46+
When updating `AUTH_LDAP_BIND_DN`, you can write out the account info in two
47+
ways. Both are documented in the config below.
48+
49+
This config is known to work with Windows Server 2022, but should work for older
50+
versions and Samba's implementation of Active Directory.
51+
52+
```py
53+
# We are overlaying production
54+
from cvat.settings.production import *
55+
56+
# Custom code below
57+
import ldap
58+
from django_auth_ldap.config import LDAPSearch
59+
from django_auth_ldap.config import NestedActiveDirectoryGroupType
60+
61+
# Notify CVAT that we are using LDAP authentication
62+
IAM_TYPE = 'LDAP'
63+
64+
# Talking to the LDAP server
65+
AUTH_LDAP_SERVER_URI = "ldap://ad.example.com" # IP Addresses also work
66+
ldap.set_option(ldap.OPT_REFERRALS, 0)
67+
68+
_BASE_DN = "CN=Users,DC=ad,DC=example,DC=com"
69+
70+
# Authenticating with the LDAP server
71+
AUTH_LDAP_BIND_DN = "CN=cvat_bind,%s" % _BASE_DN
72+
# AUTH_LDAP_BIND_DN = "[email protected]"
73+
AUTH_LDAP_BIND_PASSWORD = "SuperSecurePassword^21"
74+
75+
AUTH_LDAP_USER_SEARCH = LDAPSearch(
76+
_BASE_DN,
77+
ldap.SCOPE_SUBTREE,
78+
"(sAMAccountName=%(user)s)"
79+
)
80+
81+
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
82+
_BASE_DN,
83+
ldap.SCOPE_SUBTREE,
84+
"(objectClass=group)"
85+
)
86+
87+
# Mapping Django field names to Active Directory attributes
88+
AUTH_LDAP_USER_ATTR_MAP = {
89+
"user_name": "sAMAccountName",
90+
"first_name": "givenName",
91+
"last_name": "sn",
92+
"email": "mail",
93+
}
94+
95+
# Group Management
96+
AUTH_LDAP_GROUP_TYPE = NestedActiveDirectoryGroupType()
97+
98+
# Register Django LDAP backend
99+
AUTHENTICATION_BACKENDS += ['django_auth_ldap.backend.LDAPBackend']
100+
101+
# Map Active Directory groups to Django/CVAT groups.
102+
AUTH_LDAP_ADMIN_GROUPS = [
103+
'CN=CVAT Admins,%s' % _BASE_DN,
104+
]
105+
AUTH_LDAP_BUSINESS_GROUPS = [
106+
'CN=CVAT Managers,%s' % _BASE_DN,
107+
]
108+
AUTH_LDAP_WORKER_GROUPS = [
109+
'CN=CVAT Workers,%s' % _BASE_DN,
110+
]
111+
AUTH_LDAP_USER_GROUPS = [
112+
'CN=CVAT Users,%s' % _BASE_DN,
113+
]
114+
115+
DJANGO_AUTH_LDAP_GROUPS = {
116+
"admin": AUTH_LDAP_ADMIN_GROUPS,
117+
"business": AUTH_LDAP_BUSINESS_GROUPS,
118+
"user": AUTH_LDAP_USER_GROUPS,
119+
"worker": AUTH_LDAP_WORKER_GROUPS,
120+
}
121+
```
122+
### FreeIPA Example
123+
124+
The following example should allow for users to authenticate themselves against
125+
FreeIPA. This example requires a dummy user named `cvat_bind`. The configuration
126+
for the bind account does not need any special permissions.
127+
128+
When updating `AUTH_LDAP_BIND_DN`, you can only write the user info in one way,
129+
unlike with [Active Directory](#active-directory-example)
130+
131+
This config is known to work with AlmaLinux 8, but may work for other
132+
versions and flavors of Enterprise Linux.
133+
134+
```py
135+
# We are overlaying production
136+
from cvat.settings.production import *
137+
138+
# Custom code below
139+
import ldap
140+
from django_auth_ldap.config import LDAPSearch
141+
from django_auth_ldap.config import GroupOfNamesType
142+
143+
# Notify CVAT that we are using LDAP authentication
144+
IAM_TYPE = 'LDAP'
145+
146+
_BASE_DN = "CN=Accounts,DC=ipa,DC=example,DC=com"
147+
148+
# Talking to the LDAP server
149+
AUTH_LDAP_SERVER_URI = "ldap://ipa.example.com" # IP Addresses also work
150+
ldap.set_option(ldap.OPT_REFERRALS, 0)
151+
152+
# Authenticating with the LDAP server
153+
AUTH_LDAP_BIND_DN = "UID=cvat_bind,CN=Users,%s" % _BASE_DN
154+
AUTH_LDAP_BIND_PASSWORD = "SuperSecurePassword^21"
155+
156+
AUTH_LDAP_USER_SEARCH = LDAPSearch(
157+
"CN=Users,%s" % _BASE_DN,
158+
ldap.SCOPE_SUBTREE,
159+
"(uid=%(user)s)"
160+
)
161+
162+
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
163+
"CN=Groups,%s" % _BASE_DN,
164+
ldap.SCOPE_SUBTREE,
165+
"(objectClass=groupOfNames)"
166+
)
167+
168+
# Mapping Django field names to FreeIPA attributes
169+
AUTH_LDAP_USER_ATTR_MAP = {
170+
"user_name": "uid",
171+
"first_name": "givenName",
172+
"last_name": "sn",
173+
"email": "mail",
174+
}
175+
176+
# Group Management
177+
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
178+
179+
# Register Django LDAP backend
180+
AUTHENTICATION_BACKENDS += ['django_auth_ldap.backend.LDAPBackend']
181+
182+
# Map FreeIPA groups to Django/CVAT groups.
183+
AUTH_LDAP_ADMIN_GROUPS = [
184+
'CN=cvat_admins,CN=Groups,%s' % _BASE_DN,
185+
]
186+
AUTH_LDAP_BUSINESS_GROUPS = [
187+
'CN=cvat_managers,CN=Groups,%s' % _BASE_DN,
188+
]
189+
AUTH_LDAP_WORKER_GROUPS = [
190+
'CN=cvat_workers,CN=Groups,%s' % _BASE_DN,
191+
]
192+
AUTH_LDAP_USER_GROUPS = [
193+
'CN=cvat_users,CN=Groups,%s' % _BASE_DN,
194+
]
195+
196+
DJANGO_AUTH_LDAP_GROUPS = {
197+
"admin": AUTH_LDAP_ADMIN_GROUPS,
198+
"business": AUTH_LDAP_BUSINESS_GROUPS,
199+
"user": AUTH_LDAP_USER_GROUPS,
200+
"worker": AUTH_LDAP_WORKER_GROUPS,
201+
}
202+
```
203+
204+
### Resources
205+
- [Microsoft - LDAP Distinguished Names](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ldap/distinguished-names)
206+
- Elements that make up a distinguished name. Used with user/group searches.
207+
- [Django LDAP Reference Manual](https://django-auth-ldap.readthedocs.io/en/latest/reference.html)
208+
- Other options that can be used for LDAP authentication in Django.
209+
- [Django LDAP guide using Active Directory (Unofficial)](https://techexpert.tips/django/django-ldap-authentication-active-directory)
210+
- This is not specific to CVAT but can provide insight about firewall rules.
211+

0 commit comments

Comments
 (0)