legacy27
parent 169141c918
commit b27688a008

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from calculate.lib.cl_template import TemplateFormat
from calculate.lib.cl_ldap import LDIFAdd, LDIFError
from calculate.lib.cl_lang import setLocalTranslate
_ = lambda x: x
setLocalTranslate('cl_ldap3', sys.modules[__name__])
class ldif(TemplateFormat):
"""
LDIF формат (применяется для изменения базы данных LDAP)
"""
text = ""
def __init__(self, text):
self.text = text
def textToXML(self):
return self.text
def processingFile(self, textConfigFile, rootPath=None):
"""Обработка конфигурационного файла"""
ldap_connect = self.objVar.Get('ldap.cl_ldap_connect')
#print self.text
try:
LDIFAdd(self.text, ldap_connect.conLdap).parse()
except LDIFError as e:
self.setError("LDIF: %s" % str(e))
#except ValueError as e:
# self.setError("LDIF: %s" % str(e))
return ""

@ -15,7 +15,13 @@
# limitations under the License.
import sys
import os
from os import path
from calculate.core.server.func import MethodsInterface
from calculate.server.server import Server
from calculate.lib.utils.files import listDirectory
from calculate.lib.cl_ldap import LDAPConnectError, ldap
import shutil
_ = lambda x: x
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
@ -23,10 +29,12 @@ from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
setLocalTranslate('cl_ldap3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class LdapError(Exception):
pass
class Ldap(MethodsInterface):
class Ldap(Server):
"""Основной объект для выполнения действий связанных
с настройкой LDAP сервиса
@ -36,5 +44,77 @@ class Ldap(MethodsInterface):
Setup = "ldap_setup"
All = (Setup,)
class Service(object):
LDAP = "slapd"
def init(self):
pass
def preconfigureTemplates(self):
"""
Выполнить шаблоны для предварительной конфигурации
"""
self.clVars.Set('cl_ldap_preconfigure_set', 'on', force=True)
try:
return self.applyTemplates("/", False, False, "/", False, True)
finally:
self.clVars.Set('cl_ldap_preconfigure_set', 'off', force=True)
def set_ldap_connection(self, binddn, bindpw):
self.clVars.Set('ldap.cl_ldap_bind_dn', binddn, force=True)
self.clVars.Set('ldap.cl_ldap_bind_pw', bindpw, force=True)
return True
def clear_directory(self, rmpath):
"""
Удалить каталог
"""
for fname in listDirectory(rmpath, fullPath=True):
if path.isdir(fname):
shutil.rmtree(fname)
else:
os.unlink(fname)
def remove_ldap_db(self, database_path):
"""
Удалить базу LDAP
"""
try:
self.clear_directory(database_path)
except OSError:
raise LdapError(_("Failed to erase LDAP database"))
return True
def remove_ldap_branch(self, branch):
"""
Удалить указанную ветку LDAP
:param branch: удаляемая ветка
:return:
"""
ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
try:
try:
dn_list = ldap_connect.conLdap.search_s(branch,
ldap.SCOPE_SUBTREE,
'(objectclass=*)',
[''])
except ldap.NO_SUCH_OBJECT as e:
self.printWARNING(_("Unix LDAP branch not found"))
return True
except ldap.LDAPError as e:
raise LdapError("searchDN: " + e[0]['desc'])
for dn, f in sorted(dn_list, key=lambda x: len(x[0]), reverse=True):
try:
ldap_connect.conLdap.delete_s(dn)
except ldap.LDAPError, e:
raise LdapError("deleteDN: " + e[0]['desc'])
except LDAPConnectError as e:
raise LdapError(str(e))
return True
def save_variables(self):
for varname in ('ldap.ld_base_root',):
header, o, writename = varname.partition(".")
self.clVars.Write(writename, self.clVars.Get(varname),
header=header)
return True

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import hashlib
import base64
from calculate.lib.utils.common import genpassword
_ = lambda x: x
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
setLocalTranslate('cl_ldap3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
ALL_BYTE_VALUES = "".join(chr(x) for x in xrange(256))
class SlapPasswd(object):
"""
Получить хэш из пароля
"""
def __init__(self, hashtype):
self._hash = hashtype
def _default(self, secret):
pass
def _generate_salt(self, salt_len=4, salt_chars=ALL_BYTE_VALUES):
return genpassword(salt_len, salt_chars)
def _sha1_base64(self, secret):
return base64.b64encode(hashlib.sha1(secret).digest())
def _salted_sha1_base64(self, secret):
salt = self._generate_salt()
return base64.b64encode("%s%s" % (
hashlib.sha1("%s%s" % (secret, salt)).digest(), salt))
def get_hash(self, secret):
return "%s%s" % (
self._hash,
{
'{SHA}': self._sha1_base64,
'{SSHA}': self._salted_sha1_base64
}.get(self._hash, self._default)(secret))

@ -19,13 +19,38 @@ from calculate.core.server.func import Action, Tasks
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.cl_template import TemplatesError
from calculate.lib.utils.files import FilesError
from ..ldap import LdapError
from calculate.lib.datavars import VariableError
from calculate.server.variables.action import Actions
from ..ldap import LdapError, Ldap
from calculate.server.server import ServerError
_ = lambda x: x
setLocalTranslate('cl_ldap3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class MetaTasks(object):
def __init__(self, obj):
self.obj = obj
def ldif_task(self, ldap_params, action):
return [
{'name': 'set_ldif',
'method': '%s.set_ldap_connection(%s)' % (self.obj, ldap_params)
},
{'name': 'ldif_action',
'method': '%s.set_server_action("%s")' % (self.obj, Actions.Ldif),
},
{'name': 'ldif',
'method': '%s.applyTemplates(install.cl_source,'
'False,True,None,False,True)' % self.obj,
},
{'name': 'ldif_action',
'method': '%s.set_server_action("%s")' % (self.obj, action),
},
]
class ClLdapSetupAction(Action):
"""
Действие обновление конфигурационных файлов
@ -33,15 +58,92 @@ class ClLdapSetupAction(Action):
# ошибки, которые отображаются без подробностей
native_error = (FilesError,
TemplatesError,
VariableError,
ServerError,
LdapError)
successMessage = __("SUCCESS")
failedMessage = __("FAILED")
interruptMessage = __("INTERRUPT")
successMessage = __("LDAP server configured!")
failedMessage = __("Failed to configure LDAP server!")
interruptMessage = __("LDAP configuration manually interrupted")
meta_tasks = MetaTasks("Ldap")
# список задач для удаления сервера
uninstall_tasks = [
{'name': 'clear_creds',
'method': 'Server.clear_service_data("all")',
'condition': lambda Get: Get('server.sr_ldap_set') == 'on'
},
{'name': 'unset_ldap',
'method': 'Server.service_uninstall("ldap")',
'condition': lambda Get: Get('server.sr_ldap_set') == 'on'
},
]
stop_tasks = [
{'name': 'noautorun',
'method': 'Server.autorun_disable("%s")' % Ldap.Service.LDAP,
},
{'name': 'stop_slapd',
'message': __("Stopping LDAP service"),
'method': 'Server.stop_service("%s")' % Ldap.Service.LDAP,
},
]
# список задач для конфигурирования сервера
configure_task = [
]
# список задач для действия
tasks = [
{'name': 'test',
'message': 'test'
}
{'name': 'uninstall',
'tasks': uninstall_tasks,
},
{'name': 'stop',
'tasks': stop_tasks,
},
{'name': 'preconfigure',
'message': __("Pre-configure LDAP"),
'method': 'Ldap.preconfigureTemplates()',
},
{'name': 'remove_old_db',
'method': 'Ldap.remove_ldap_db(ld_database_path)'
},
{'name': 'start_slapd',
'message': __("Starting LDAP service"),
'method': 'Server.start_service("%s")' % Ldap.Service.LDAP,
},
{'name': 'apply_ldif',
'tasks': meta_tasks.ldif_task("ld_temp_dn,ld_temp_pw", Actions.Setup)
},
{'name': 'templates',
'message': __("Configure LDAP"),
'method': 'Server.applyTemplates(install.cl_source,'
'False,True,None,True,True)',
},
{'name': 'restart_slapd',
'message': __("Restarting LDAP service"),
'method': 'Server.restart_service("%s")' % Ldap.Service.LDAP,
},
{'name': 'save_creds',
'method': 'Server.save_service_data("admin",ld_admin_dn,ld_admin_pw)'
},
{'name': 'autorun',
'method': 'Server.autorun_enable("%s")' % Ldap.Service.LDAP,
},
{'name': 'set_ldap',
'method': 'Server.service_install("ldap")'
},
{'name': 'save_data',
'method': 'Ldap.save_variables()'
}
]
@classmethod
def register_stop(cls, stop_tasks):
cls.stop_tasks.extend(stop_tasks)
@classmethod
def register_uninstall(cls, uninstall_tasks):
cls.uninstall_tasks.extend(uninstall_tasks)

@ -20,18 +20,3 @@ from calculate.lib.datavars import ActionVariable
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_ldap3', sys.modules[__name__])
class Actions(object):
Setup = "ldap_setup"
class VariableAcLdapSetup(ActionVariable):
"""
Action variable which has value "on" for prepare squash
"""
def action(self, cl_action):
if cl_action == Actions.Setup:
return "on"
return "off"

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from calculate.lib.datavars import (ReadonlyVariable, Variable,
VariableInterface, VariableError)
from calculate.lib.utils.common import genpassword
from calculate.ldap.tools import SlapPasswd
from calculate.lib.utils.tools import repeater
from calculate.lib.cl_ldap import LDAPConnect, LDAPConnectError, ldap
from calculate.lib.configparser import (ConfigParserLocked,
Error as ConfigParserError)
_ = lambda x: x
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
setLocalTranslate('cl_ldap3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class ServerEnvHelper(VariableInterface):
"""
Получение значений из env файла или fallback
"""
fallback_variable = ""
fallback_value = ""
service = ""
parameter = ""
def get(self):
cp_path = self.Get('server.cl_server_env_path')
cp = ConfigParserLocked(cp_path)
try:
with cp.lock_read() as cp:
value = cp.get(self.service, self.parameter,
fallback=None)
if value is None:
if self.fallback_variable:
return self.Get(self.fallback_variable)
else:
return self.fallback_value
else:
return value.encode('utf-8')
except ConfigParserError:
raise VariableError(_("Failed to remove server parameters"))
class LdapMaxHelper(VariableInterface):
"""
Получение максимального значение из среди атрибутов
"""
type = "int"
base_dn = ""
search_filter = ""
attr = ""
def get_max(self):
ldap_connect = self.Get('ldap.cl_ldap_connect')
if ldap_connect:
base_dn = self._value_formatter.format(self.base_dn, self.Get)
try:
return max(int(x) for x in ldap_connect.ldap_simple_search(
base_dn, self.search_filter, self.attr) if x.isdigit())
# max(empty_list)
except ValueError:
return None
else:
return None
def get(self):
return str(self.get_max() or "")
class LdapSearchHelper(VariableInterface):
"""
Проверка свободен ли указанный идентификатор
"""
base_dn = ""
search_filter = "uid={value}"
def value_get(self, value):
def get_wrapper(val):
if val == "value":
return value
else:
return self.Get(val)
return get_wrapper
def check_name(self, value):
ldap_connect = self.Get('ldap.cl_ldap_connect')
if ldap_connect:
base_dn = self._value_formatter.format(self.base_dn,
self.value_get(value))
search_filter = self._value_formatter.format(self.search_filter,
self.value_get(value))
print "DEBUG Search:", base_dn, search_filter
return any(ldap_connect.ldap_search(
base_dn, ldap.SCOPE_ONELEVEL, search_filter))
else:
return None
class HashHelper(VariableInterface):
"""
Хэш пароля для LDAP
"""
source = ""
hash_var = "ldap.ld_encrypt"
def get(self):
value = self.Get(self.source)
if value:
return SlapPasswd(self.Get(self.hash_var)).get_hash(value)
else:
return "crypt{xxx}"
class RandomPasswordHelper(VariableInterface):
"""
Генератор пароля
"""
password_len = 9
def get(self):
return genpassword(self.password_len).strip()

@ -15,6 +15,208 @@
# limitations under the License.
import sys
from calculate.lib.cl_lang import setLocalTranslate
from calculate.lib.datavars import (ReadonlyVariable, Variable,
VariableInterface, VariableError)
from calculate.lib.utils.tools import repeater
from calculate.lib.cl_ldap import LDAPConnect, LDAPConnectError
from helpers import ServerEnvHelper, HashHelper, RandomPasswordHelper
_ = lambda x: x
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
setLocalTranslate('cl_ldap3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class VariableLdBaseRoot(Variable):
"""
Имя для базового суффикса
"""
value = "calculate"
opt = ("-b", "--basedn")
metavalue = "BASEDN"
def init(self):
self.label = _("Root base DN")
self.help = "set root base DN"
def set(self, value):
if value.startswith("dc="):
return value[3:]
return value
class VariableLdBaseDn(ReadonlyVariable):
"""
Базовый суффикс LDAP
"""
value_format = "dc={ld_base_root}"
def init(self):
self.label = _("Base DN")
class VariableLdBindLogin(Variable):
"""
Пользователь для чтения
"""
value = "proxyuser"
class VariableLdBindDn(ReadonlyVariable):
"""
Bind суффикс LDAP
"""
value_format = "cn={ld_bind_login},{ld_base_dn}"
class VariableLdBindPw(ReadonlyVariable):
"""
Пароль для подключения
"""
value = "calculate"
class VariableLdBindHash(HashHelper, ReadonlyVariable):
"""
Хэш рут пароля
"""
source = "ld_bind_pw"
class VariableLdTempDn(ReadonlyVariable):
"""
Временный DN для подключения
"""
value_format = "cn=ldaproot,{ld_base_dn}"
class VariableLdTempPw(RandomPasswordHelper, ReadonlyVariable):
"""
Временный пароль для подключения к LDAP
"""
password_len = 9
def get(self):
return "test"
class VariableLdTempHash(HashHelper, ReadonlyVariable):
"""
Временный пароль для подключения к LDAP
"""
source = "ld_temp_pw"
class VariableClLdapPreconfigureSet(ReadonlyVariable):
"""
Предварительное наложение шаблонов
"""
type = "bool"
value = "off"
class VariableLdAdminDn(ReadonlyVariable):
"""
DN root пользователя
"""
value_format = "cn={ld_admin_login},{ld_base_dn}"
class VariableLdAdminLogin(ReadonlyVariable):
"""
Имя пользователя root
"""
value = "ldapadmin"
class VariableLdEncrypt(ReadonlyVariable):
"""
Алгоритм шифрования пароля
"""
value = "{SSHA}"
class VariableLdAdminHash(HashHelper, ReadonlyVariable):
"""
Хэш рут пароля
"""
source = "ld_admin_pw"
class VariableLdAdminPw(ServerEnvHelper, RandomPasswordHelper, Variable):
"""
Пароль root
"""
password_len = 9
service = "admin"
parameter = "pass"
@property
def fallback_value(self):
return "test"
# return RandomPasswordHelper.get(self)
class VariableLdServices(ReadonlyVariable):
"""
Имя всех сервисов
"""
value = "Services"
class VariableLdServicesDn(ReadonlyVariable):
"""
DN для всех сервисов
"""
value_format = "ou={ld_services},{ld_base_dn}"
class VariableLdDatabasePath(Variable):
"""
Путь до базы LDAP
"""
value = "/var/lib/openldap-data"
class VariableClLdapHost(Variable):
"""
Узел LDAP
"""
value = "localhost"
class VariableClLdapBindDn(Variable):
"""
Переменная используется для соединения с LDAP
"""
value = ""
class VariableClLdapBindPw(Variable):
"""
Переменная используется для соединения с LDAP
"""
value = ""
class VariableClLdapConnect(ReadonlyVariable):
"""
Объект соединение с LDAP
"""
type = "object"
def get(self):
bind_dn = self.Get('cl_ldap_bind_dn')
bind_pw = self.Get('cl_ldap_bind_pw')
ldap_host = self.Get('cl_ldap_host')
if bind_dn and bind_pw:
error = ""
for x in repeater(0.2, 0.4, 0.8):
try:
return LDAPConnect(bind_dn, bind_pw, host=ldap_host)
except LDAPConnectError as e:
error = str(e)
raise VariableError(_("Failed to connect to LDAP server")
+ _(": ") + error)
return ""

@ -20,7 +20,8 @@ from calculate.lib.datavars import VariableError, DataVarsError
from calculate.core.server.func import WsdlBase
from .ldap import Ldap, LdapError
from .variables.action import Actions as LdapActions
from calculate.server.server import Server
from calculate.server.variables.action import Actions as ServerActions
from utils.cl_ldap_setup import ClLdapSetupAction
_ = lambda x: x
@ -39,11 +40,11 @@ class Wsdl(WsdlBase):
# идентификатор метода
'method_name': Ldap.Method.Setup,
# категория метода
'category': __('LDAP'),
'category': __('Setup Server'),
# заголовок метода
'title': __("Setup"),
'title': __("LDAP"),
# иконка для графической консоли
'image': 'setup',
'image': 'server-database',
# метод присутствует в графической консоли
'gui': True,
# консольная команда
@ -51,21 +52,27 @@ class Wsdl(WsdlBase):
# права для запуска метода
'rights': ['ldap'],
# объект содержащий модули для действия
'logic': {'Ldap': Ldap},
'logic': {'Ldap': Ldap,
'Server': Server},
# описание действия
'action': ClLdapSetupAction,
# объект переменных
'datavars': "ldap",
'native_error': (VariableError, DataVarsError, LdapError),
# значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': LdapActions.Setup},
'setvars': {'cl_action!': ServerActions.Setup,
'server.cl_server_name!': "ldap",
'cl_autoupdate_set': 'on'
# 'cl_dispatch_conf_default': "usenew"
},
# описание груп (список лямбда функций)
'groups': [
lambda group: group(
_("Repository"),
brief=(),
hide=(),
normal=(),
_("LDAP server"),
brief=('ld_base_dn',
'server.sr_ldap_set'),
hide=('ld_base_root',),
normal=('ld_base_root',),
expert=()),
],
'brief': {'next': __("Perform"),

@ -32,6 +32,8 @@ packages = [
if '__init__.py' in files
]
print packages
setup(
name=__app__,
version=__version__,
@ -40,5 +42,6 @@ setup(
author_email="support@calculate.ru",
url="http://calculate-linux.org",
license="http://www.apache.org/licenses/LICENSE-2.0",
package_dir = {'calculate.ldap': "pym/ldap"},
packages = packages)
package_dir = {'calculate.ldap': "pym/ldap",
'calculate.lib.format': 'pym/format'},
packages = packages + ["calculate.lib.format"])

Loading…
Cancel
Save