django-environ - Managing LDAP DN in .env

164 views Asked by At

I have a django web app, with a middleware that intercepts incoming requests, extracts user details (added to header by upstream middleware) in the request header, and checks if user is authorized to access the page if user is member of a distribution group.

I'm using django-environ to manage my environment variables so i can modify the list of DL Groups which can access my page without changing the code.

# in Middleware, only included important part of code
from django.conf import settings

MINIMAL_MEMBERSHIP = settings.AUTHORIZED_MEMBERSHIP_REQUIREMENT # This should pass in as a list
server_object = Server(LDAP_SERVER)
conn = Connection(server_object, LDAP_USER, LDAP_PASS, client_strategy=SAFE_SYNC, auto_bind=True)
status, result, response, _ = conn.search(
            search_base=requester_dn,
            search_filter = '(objectClass=User)',
            attributes = ['memberOf']
            ) 

authorized = False
requester_membership_list = response[0]['raw_attributes']['memberOf']
for membership in requester_membership_list:
    ad_group_name = membership.decode('utf-8')
    if ad_group_name in MINIMAL_MEMBERSHIP:
        authorized = True
        break
# In settings.py

AUTHORIZED_MEMBERSHIP_REQUIREMENT = env.list('AUTHORIZED_MEMBERSHIP_REQUIREMENT')

# In .env 
AUTHORIZED_MEMBERSHIP_REQUIREMENT="CN=Virtualisation team,OU=Distribution Group,OU=Exchange,OU=APPS,DC=xxx,DC=xxx,DC=xxx,DC=com",

According to django-environ, you can read .env as a list like

# .env
LIST_ENV=one,two,three,four

# settings.py
LIST_ENV=env.list(LIST_ENV)
print(LIST_ENV) # outputs ['one', 'two', 'three', 'four']

But understandably ldap DN format will break this as a full DN is already delimited by commas, so:

# .env
DN_LIST="CN=1,OU=1,OU=1,OU=1,DC=xxx,DC=xxx,DC=xxx,DC=com","CN=2,OU=2,OU=2,OU=2,DC=xxx,DC=xxx,DC=xxx,DC=com"
# settings.py
DN_LIST=env.list(DN_LIST)

# Actual Behavior
print(DN_LIST) 
# DN_LIST = ['CN=1', 'OU=1', 'OU=1', ...]
# len(DN_LIST) will output 16

I would like achieve this:

# Behavior i want
print(DN_LIST) 
# DN_LIST = ["CN=1,OU=1,OU=1,OU=1,DC=xxx,DC=xxx,DC=xxx,DC=com","CN=2,OU=2,OU=2,OU=2,DC=xxx,DC=xxx,DC=xxx,DC=com"]
# len(DN_LIST) will output 2

Is there anyway to do this, or maybe any alternatives to manage the list from .env without modifying the code if i need to add/remove new groups?

Thank you

2

There are 2 answers

1
Honhonhon On

Sometimes taking a night off provides a simple solution to an otherwise simple problem.. heh.

Decided to take the DN List in .env as a string and have the DNs delimited by something (e.g. ;) and manually split/process it into a list.

# .env
AUTHORIZED_MEMBERSHIP_REQUIREMENT=CN=1,OU=1,OU=1,OU=1,DC=xxx,DC=xxx,DC=xxx,DC=com;CN=2,OU=2,OU=2,OU=2,DC=xxx,DC=xxx,DC=xxx,DC=com

# .settings.py
AUTHORIZED_MEMBERSHIP_REQUIREMENT = env.str('AUTHORIZED_MEMBERSHIP_REQUIREMENT').split(';')
0
Bao Tran On

This is about how you read the shell environment variable (.env) into python

DN_LIST="CN=1,OU=1,OU=1,OU=1,DC=xxx" ## instead this 

DN_LIST_NEW='["CN=1,OU=1,OU=1,OU=1,DC=xxx","CN=2,OU=2,OU=2,OU=2,DC=xxx"]' ## please you this 

Off-topic: define these DN in .env means if we want to change the DN values, we have to change in .env and **restart/deploy** the application , which is not good. You should think about put these DN values into a table in database