Commit f8f51c67 authored by Gero Müller's avatar Gero Müller
Browse files

fix setup.py, add ldap-export extension, minor fixes

parent 6fe2f0a3
......@@ -27,5 +27,4 @@ docs/source/py
*.sublime-workspace
.vagrant
vagrant_ansible_inventory_default
vispa/extensions
node_modules
\ No newline at end of file
......@@ -213,7 +213,7 @@ def parse_commandline():
default=os.path.join(default_base, "var"),
help='Directory containing server '
'data and cache files (default: %s)'
% os.path.join(default_base, "conf"))
% os.path.join(default_base, "var"))
parser.add_argument('-p', '--port',
default=None,
help='which port the server shall listen on')
......
......@@ -6,12 +6,12 @@
[alembic]
# NOTE: alembic is ignored and never used in case of an sqlite database
use_alembic = True
# inplace installation
script_location = vispa/models/alembic
# global installation
#script_location = vispa:models/alembic
auto_migrate = True
[web]
......@@ -148,3 +148,22 @@ role_3_permissions = ["project.read_items", "project.create_items", "project.edi
# assignment of roles to user and guest group
user_group_roles = [1]
guest_group_roles = []
[ldap-export]
enable = False
url = ldap:///
user = cn=admin,dc=vispa,dc=local
password = changeme
# where to create the entries
user_base = ou=people,dc=vispa,dc=local
group_base = ou=group,dc=vispa,dc=local
# add the following offset to all user ids
uid_offset = 1000
gid_offset = 1000
# create all missing users on startup
sync_on_startup = False
......@@ -3,13 +3,14 @@
from setuptools import setup
from distutils.util import convert_path
import os
ignore_extensions = [".py", ".pyc", ".pyo", ".orig"]
files = []
packages = []
srcdir = os.path.dirname(os.path.abspath(__file__))
for wroot, wdirs, wfiles in os.walk("vispa"):
for name in wfiles:
if name == "__init__.py":
......@@ -26,7 +27,7 @@ for wroot, wdirs, wfiles in os.walk(versions_path):
# http://stackoverflow.com/a/24517154
version_ns = {}
version_path = convert_path('vispa/version.py')
version_path = os.path.join(srcdir, 'vispa', 'version.py')
with open(version_path) as version_file:
exec(version_file.read(), version_ns)
......@@ -40,11 +41,11 @@ setup(
license="GNU GPL v2",
packages=packages,
package_data={"vispa": files},
scripts=["bin/vispa", "bin/vispad"],
scripts=[os.path.join(srcdir, 'bin', 'vispa'), os.path.join(srcdir, 'bin', 'vispad')],
install_requires=["sqlalchemy >= 0.9.0", "mako", "cherrypy",
"paramiko", "rpyc",
"alembic >= 0.7.3", # for Operations.batch_alter_table
"passlib", "ws4py"],
"passlib", "ws4py", "ldap3"],
extras_require={"doc": ["sphinx", "sphinx-bootstrap-theme"]},
classifiers=[
"Development Status :: 5 - Production/Stable",
......
# -*- coding: utf-8 -*-
import logging
import vispa
from vispa.models.user import User
from vispa.server import AbstractExtension
from sqlalchemy.orm import scoped_session, sessionmaker
import ldap3
from ldap3.utils.log import set_library_log_detail_level, OFF, BASIC, NETWORK, EXTENDED
from ldap3.core.exceptions import LDAPNoSuchObjectResult
logger = logging.getLogger(__name__)
class LDAPExportExtension(AbstractExtension):
def name(self):
return "ldap-export"
def dependencies(self):
return []
def setup(self):
url = vispa.config("ldap-export", "url")
user = vispa.config("ldap-export", "user")
password = vispa.config("ldap-export", "password")
set_library_log_detail_level(BASIC)
if url:
self.connection = ldap3.Connection(url, user, password, auto_bind=True, raise_exceptions=True)
else:
self.connection = None
logger.info(self.connection)
if self.connection:
self.user_base = vispa.config("ldap-export", "user_base")
self.group_base = vispa.config("ldap-export", "group_base")
self.uid_offset = vispa.config("ldap-export", "uid_offset", 1000)
self.gid_offset = vispa.config("ldap-export", "gid_offset", 1000)
vispa.register_callback("user.activate", self.user_add)
vispa.register_callback("user.set_password", self.user_set_password)
if vispa.config("ldap-export", "sync_on_startup", False):
if vispa.config("ldap-export", "delete_unknown", False):
self.delete_unknown()
self.sync_all_users()
def delete_unknown(self):
session = scoped_session(sessionmaker(autoflush=True, autocommit=False))
session.configure(bind=self.server._engine)
try:
active_users = session.query(User, User.name).filter_by(status=User.ACTIVE).all()
self.connection.search(self.user_base, "(objectClass=posixAccount)", attributes=['uid'])
for ldap_user in self.connection.entries:
if ldap_user.uid not in active_users:
logger.info("Deleting unknown ldap user: %s", ldap_user.entry_get_dn())
self.connection.delete(ldap_user.entry_get_dn())
self.connection.search(self.group_base, "(objectClass=posixGroup)", attributes=['cn'])
for ldap_group in self.connection.entries:
if ldap_group.cn not in active_users:
logger.info("Deleting unknown ldap group: %s", ldap_group.entry_get_dn())
self.connection.delete(ldap_group.entry_get_dn())
except:
logger.exception("remove_invalid_ldap_entries")
finally:
session.remove()
def sync_all_users(self):
session = scoped_session(sessionmaker(autoflush=True, autocommit=False))
session.configure(bind=self.server._engine)
try:
users = session.query(User).filter_by(status=User.ACTIVE)
for user in users:
try:
self.user_add(user)
except:
pass
except:
logger.exception("sync_all_users")
finally:
session.remove()
def user_delete(self, user):
dn = 'cn=%s,%s' % (unicode(user.name), self.user_base)
logger.info("Delete user: %s", dn)
self.connection.delete(dn)
dn = 'cn=%s,%s' % (unicode(user.name), self.group_base)
logger.info("Delete group: %s", dn)
self.connection.delete(dn)
def user_add(self, user):
dn = 'cn=%s,%s' % (unicode(user.name), self.user_base)
classes = ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'posixAccount', 'shadowAccount']
attributes = {
'uid': unicode(user.name),
'cn': unicode(user.name),
'sn': unicode(user.name),
'userPassword': '{CRYPT}' + unicode(user.password),
'loginShell': '/bin/bash',
'uidNumber': user.id + self.uid_offset,
'gidNumber': user.id + self.gid_offset,
'homeDirectory': '/home/%s/' % unicode(user.name)
}
logger.info("Add user: %s, %s, %s", dn, classes, attributes)
self.connection.add(dn, classes, attributes)
dn = 'cn=%s,%s' % (unicode(user.name), self.group_base)
classes = ['top', 'posixGroup']
attributes = {
'cn': unicode(user.name),
'gidNumber': user.id + self.gid_offset,
}
logger.info("Add group: %s, %s, %s", dn, classes, attributes)
self.connection.add(dn, classes, attributes)
def user_set_password(self, user):
dn = 'cn=%s,%s' % (unicode(user.name), self.user_base)
changes = {
'userPassword': (2, '{CRYPT}' + unicode(user.password))
}
logger.info("Change password: %s, %s", dn, changes)
self.connection.modify(dn, changes)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment