|
|
@ -5,8 +5,16 @@ import octoprint.plugin |
|
|
|
from octoprint.users import FilebasedUserManager, User |
|
|
|
from octoprint.users import FilebasedUserManager, User |
|
|
|
from octoprint.settings import settings |
|
|
|
from octoprint.settings import settings |
|
|
|
import ldap |
|
|
|
import ldap |
|
|
|
|
|
|
|
import ldap3 |
|
|
|
|
|
|
|
import ldap3.utils.dn |
|
|
|
import uuid |
|
|
|
import uuid |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LDAP_SERVER = ldap3.Server("pool.ldap.ehlab.uk", tls=ldap3.Tls(validate=ssl.CERT_REQUIRED, version=ssl.PROTOCOL_TLSv1_2)) |
|
|
|
|
|
|
|
LDAP_BASE = 'dc=edinburghhacklab,dc=com' |
|
|
|
|
|
|
|
LDAP_GROUPS = ["octoprint"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LDAPUserManager(FilebasedUserManager, |
|
|
|
class LDAPUserManager(FilebasedUserManager, |
|
|
|
octoprint.plugin.SettingsPlugin, |
|
|
|
octoprint.plugin.SettingsPlugin, |
|
|
@ -17,27 +25,59 @@ class LDAPUserManager(FilebasedUserManager, |
|
|
|
# - chaeckPassword called, if it return True |
|
|
|
# - chaeckPassword called, if it return True |
|
|
|
# - login_user called with User returned by previous findUser |
|
|
|
# - login_user called with User returned by previous findUser |
|
|
|
|
|
|
|
|
|
|
|
def checkPassword(self, username, password): |
|
|
|
def ldapify_groups(self, groups): |
|
|
|
try: |
|
|
|
output = [] |
|
|
|
connection = self.getLDAPClient() |
|
|
|
for group in groups: |
|
|
|
|
|
|
|
output.append('cn={},ou=Groups,ou=People,dc=edinburghhacklab,dc=com'.format(group)) |
|
|
|
|
|
|
|
return output |
|
|
|
|
|
|
|
|
|
|
|
username = self.escapeLDAP(username) |
|
|
|
|
|
|
|
dn = self.findLDAPUser(username) |
|
|
|
|
|
|
|
if dn is None: |
|
|
|
|
|
|
|
return False |
|
|
|
|
|
|
|
connection.bind_s(dn, password) |
|
|
|
|
|
|
|
connection.unbind_s() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
user = FilebasedUserManager.findUser(self, username) |
|
|
|
def check_auth(self, username, password): |
|
|
|
if not user: |
|
|
|
if username in [None, ''] or password in [None, '']: |
|
|
|
self._logger.debug("Add new user") |
|
|
|
return None |
|
|
|
self.addUser(username, str(uuid.uuid4()), True) |
|
|
|
ldap_conn = ldap3.Connection(LDAP_SERVER, auto_bind=ldap3.AUTO_BIND_TLS_BEFORE_BIND) |
|
|
|
return True |
|
|
|
ldap_conn.search(search_base=LDAP_BASE, |
|
|
|
|
|
|
|
search_filter='(&(objectClass=account)(uid={}))'.format(username), |
|
|
|
|
|
|
|
search_scope=ldap3.SUBTREE, |
|
|
|
|
|
|
|
attributes=['uid', 'memberOf']) |
|
|
|
|
|
|
|
if len(ldap_conn.response) > 0: |
|
|
|
|
|
|
|
dn = ldap_conn.response[0]['dn'] |
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
bind_conn = ldap3.Connection(LDAP_SERVER, user=dn, password=password, auto_bind=ldap3.AUTO_BIND_TLS_BEFORE_BIND) |
|
|
|
|
|
|
|
if bind_conn: |
|
|
|
|
|
|
|
return ldap_conn.response[0]['attributes'] |
|
|
|
|
|
|
|
except ldap3.core.exceptions.LDAPBindError: |
|
|
|
|
|
|
|
pass |
|
|
|
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def checkPassword(self, username, password): |
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
#connection = self.getLDAPClient() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#username = self.escapeLDAP(username) |
|
|
|
|
|
|
|
#dn = self.findLDAPUser(username) |
|
|
|
|
|
|
|
#if dn is None: |
|
|
|
|
|
|
|
# return False |
|
|
|
|
|
|
|
#connection.bind_s(dn, password) |
|
|
|
|
|
|
|
#connection.unbind_s() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data = check_auth(self, username, password) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for group in ldapify_groups(LDAP_GROUPS): |
|
|
|
|
|
|
|
if group in data.get('memberOf', []): |
|
|
|
|
|
|
|
user = FilebasedUserManager.findUser(self, username) |
|
|
|
|
|
|
|
if not user: |
|
|
|
|
|
|
|
self._logger.debug("Add new user") |
|
|
|
|
|
|
|
self.addUser(username, str(uuid.uuid4()), True) |
|
|
|
|
|
|
|
return True |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
self._logger.error("LDAP-CAMERON: user or password incorrect."") |
|
|
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
except ldap.INVALID_CREDENTIALS: |
|
|
|
except ldap.INVALID_CREDENTIALS: |
|
|
|
self._logger.error("LDAP : Your username or password is incorrect.") |
|
|
|
self._logger.error("LDAP : Your username or password is incorrect.") |
|
|
|
return FilebasedUserManager.checkPassword(self, username, password) |
|
|
|
return FilebasedUserManager.checkPassword(self, username, password) |
|
|
|
except ldap.LDAPError, e: |
|
|
|
except Exception as e: |
|
|
|
if type(e.message) == dict: |
|
|
|
if type(e.message) == dict: |
|
|
|
for (k, v) in e.message.iteritems(): |
|
|
|
for (k, v) in e.message.iteritems(): |
|
|
|
self._logger.error("%s: %sn" % (k, v)) |
|
|
|
self._logger.error("%s: %sn" % (k, v)) |
|
|
@ -54,9 +94,8 @@ class LDAPUserManager(FilebasedUserManager, |
|
|
|
local_user = FilebasedUserManager.findUser(self, userid, apikey, session) |
|
|
|
local_user = FilebasedUserManager.findUser(self, userid, apikey, session) |
|
|
|
#If user not exists in local database, search it on LDAP |
|
|
|
#If user not exists in local database, search it on LDAP |
|
|
|
if userid and not local_user: |
|
|
|
if userid and not local_user: |
|
|
|
if(self.findLDAPUser(userid)): |
|
|
|
|
|
|
|
#Return a fake user instance |
|
|
|
#Return a fake user instance |
|
|
|
return User(userid, str(uuid.uuid4()), True, ["user"]) |
|
|
|
return User(userid, str(uuid.uuid4()), True, ["user"]) |
|
|
|
|
|
|
|
|
|
|
|
else: |
|
|
|
else: |
|
|
|
return None |
|
|
|
return None |
|
|
|