This script allows users to log in to Home Assistant using their sAMAccountName or userPrincipalName identifiers without any special requirements for the ldapsearch or curl utilities. Instead, it requires the ldap3 Python module, but there are ways to install that locally so it can even be used in supervised / Home Assistant OS installs.
Obviously most of the configuration values in the script need to be edited to work in your environment.
SERVER- the DNS name of your AD domain, or the name or IP of a specific domain controller.HELPERDN- the DN (distinguishedNameattribute) of the service account you're using to search LDAP for the desired user.HELPERPASS- the password for that service account.TIMEOUT- LDAP search timeout in seconds.FILTER- LDAP search filter to find the desired user. To match by SAM name or UPN and a group membership, just edit thememberOfline to include the DN of the group you want to use to control access.BASEDN- the DN of the top-most container to search. To search the entire domain, use just the "DC" sections at the end of your domain's DNs, e.g.DC=ad,DC=example,DC=com. As written, the script searches recursively.
In a Home Assistant Core installation, you can install the Python module using pip or your package manager, then put the script in any directory where Home Assistant can reach it. Then add a section to configuration.yaml:
homeassistant:
auth_providers:
- type: command_line
command: /usr/local/bin/ldap-auth-ad.py
meta: true
- type: homeassistantNote that homeassistant must be explicitly specified as an authentication method, or you won't have access to locally-created users.
Because Python modules can be installed in and loaded from the current path, it's possible to make this work in Docker containers as well, by hiding it in the /config directory.
First, make a directory to contain everything, and copy the configured script into the host directory that's mounted as /config:
me@host:~ $ sudo mkdir /usr/share/hassio/homeassistant/ldap-auth
me@host:~ $ sudo cp ldap-auth-ad.py /usr/share/hassio/homeassistant/ldap-authNext, open a shell in the Home Assistant core container, and change to the directory we just created:
me@host:~ $ sudo docker exec -it homeassistant bash
bash-5.0# cd /config/ldap-authInstall the module:
bash-5.0# pip install -t . ldap3And insert the configuration section (note the modified path):
homeassistant:
auth_providers:
- type: command_line
command: /config/ldap-auth/ldap-auth-ad.py
meta: true
- type: homeassistantFinally, restart the entire application (Configuration > Server Controls > Server Management > Restart) to reload the config. (It may be possible to reload without doing this, but I'm not entirely clear on when configuration.yaml is read.)
You should now be able to log in as any user that's a member of the group you picked above. Home Assistant will create a new user in the local database the first time a user logs in.
This whole thing is hacked out of a more generic LDAP script by Rechner Fox. I mostly tweaked the filters and added the username search.
Hello, I have successfully been using your Python script for my AD and Home Assistat connection, I had to change the structure of my ADs OUs because I am replicating my works structure for future implementation of the Project I'm working on. Ever since I changed the OU Structure of my AD I cannot login with User account credentials as it will always tell me wrong Password or Username. Posted below is the python script and Configuration for home Assistant as well as the basic structure of my OUs in AD
Python Script
#!/usr/bin/env python
Config values
SERVER = "ladestation.local"
BINDDN = "LADESTATION\{}"
TIMEOUT = 3
BASEDN = "DC=ladestation,DC=local"
ADMINGROUP = f"CN=Admins,OU=groups,{BASEDN}"
USERSGROUP = f"CN=Ladestation,OU=groups,{BASEDN}"
FILTER = f"""
(&
(objectClass=person)
(sAMAccountName={{}})
(|
(memberOf={ADMINGROUP})
(memberOf={USERSGROUP})
)
)"""
Dependencies
import os
import sys
try:
from ldap3 import Server, Connection, ALL
except:
import pip
if hasattr(pip, 'main'):
pip.main(['install', 'ldap3'])
else:
pip._internal.main(['install', 'ldap3'])
from ldap3 import Server, Connection, ALL
Auth script
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
if 'username' not in os.environ or 'password' not in os.environ:
eprint("Need username and password environment variables!")
exit(1)
BINDDN = BINDDN.format(os.environ['username'])
FILTER = FILTER.format(os.environ['username'])
server = Server(SERVER, get_info=ALL)
try:
conn = Connection(server, BINDDN, password=os.environ['password'], auto_bind=True, raise_exceptions=True)
except Exception as e:
eprint("bind as {} failed: {}".format(os.environ['username'], e))
exit(1)
search = conn.search(BASEDN, FILTER, attributes=['displayName', 'memberOf'])
if len(conn.entries) > 0:
eprint("search success: username {}, result {}".format(os.environ['username'], conn.entries))
else:
eprint("search for username {} yielded empty result".format(os.environ['username']))
exit(1)
print("name = {}".format(conn.entries[0].displayName))
if ADMINGROUP in conn.entries[0].memberOf:
print("group = system-admin")
else:
print("group = system-users")
eprint("{} authenticated successfully".format(os.environ['username']))
exit(0)
Configuration
Loads default set of integrations. Do not remove.
default_config:
Load frontend themes from the themes folder
frontend:
themes: !include_dir_merge_named themes
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
LDAP Integration
homeassistant:
auth_providers:
- type: homeassistant
- type: command_line
command: "/usr/local/bin/python3"
args: ["/config/scripts/ldap-auth-ad.py"]
meta: true
AD OUs
Main folder(
computers
groups
(ADMINGROUP)
(USERGROUP)
users
admin
(admin users)
guest
staff
structure
trainee
egs
eis
im
itel
(divided by year and filled with users)
metro
any help is greatly appreciated, I have been trying to debug the situation for the past 3 days and gotten nowhere sadly.