config/sysinv/sysinv/sysinv/sysinv/puppet/ldap.py
Andy Ning d8c8412cb4 Support shared LDAP share in region config
This patch enhanced region configuration to support LDAP as shared
service optionally for both IPv4 and IPV6 management network.
By sharing LDAP service, management of system users can be
centralized at primary region.

A LDAP_SERVICE_URL=<[ldap://]ip_address[:port]> can be specified in the
[SHARED_SERVICES] section of region configuration file, the secondary
regions will then be setup and share the LDAP service running at the
specified URL of the primary region. If no LDAP_SERVICE_URL is
specified in the [SHARED_SERVICES] section, the secondary regions will
setup and use local LDAP service running at the region's controllers.

Decouple NSLCD from the open-ldap SM service and manage it by PMOND
instead. This is needed because in the Shared LDAP case, we deprovision
the open-ldap service on the Secondary Region which renders NSLCD
unmanaged.

Additionally, we allow the Secondary Region or Sub Clouds to bind
anonymously, but still need to support LDAP read operations in these
regions such as ldapfinger or lsldap. For this purpose, the ldapscripts
runtime library has been modified to allow anonymous binds during LDAP
search operations.

Change-Id: Ic9f4d157c0eab02a8dabbdae28d508d4aef05fa2
2018-06-28 22:07:38 -04:00

99 lines
3.9 KiB
Python

#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from passlib.hash import ldap_salted_sha1 as hash
from sysinv.common import constants
from . import base
class LdapPuppet(base.BasePuppet):
"""Class to encapsulate puppet operations for ldap configuration"""
SERVICE_NAME = 'open-ldap'
def get_secure_static_config(self):
password = self._generate_random_password()
passhash = hash.encrypt(password)
return {
'platform::ldap::params::admin_pw': password,
'platform::ldap::params::admin_hashed_pw': passhash,
}
def get_static_config(self):
# default values for bootstrap manifest
ldapserver_remote = False
ldapserver_host = constants.CONTROLLER
bind_anonymous = False
return {
'platform::ldap::params::ldapserver_remote': ldapserver_remote,
'platform::ldap::params::ldapserver_host': ldapserver_host,
'platform::ldap::params::bind_anonymous': bind_anonymous,
}
def get_host_config(self, host):
ldapserver_remote = False
ldapserver_host = constants.CONTROLLER
bind_anonymous = False
if self._distributed_cloud_role() == \
constants.DISTRIBUTED_CLOUD_ROLE_SUBCLOUD:
# Note: During bootstrap, sysinv db is not yet populated
# and hence local ldapserver will be configured.
# It will be then disabled when controller manifests are applied.
sys_controller_network = self.dbapi.network_get_by_type(
constants.NETWORK_TYPE_SYSTEM_CONTROLLER)
sys_controller_network_addr_pool = self.dbapi.address_pool_get(
sys_controller_network.pool_uuid)
ldapserver_remote = True
ldapserver_addr = sys_controller_network_addr_pool.floating_address
ldapserver_host = self._format_url_address(ldapserver_addr)
bind_anonymous = True
elif self._region_config():
service_config = self.get_service_config(self.SERVICE_NAME)
if service_config is not None:
ldapserver_remote = True
ldapserver_uri = service_config.capabilities.get('service_uri')
addr_index = ldapserver_uri.rfind('/')
ldapserver_host = ldapserver_uri[addr_index + 1:]
bind_anonymous = True
if host.personality != constants.CONTROLLER:
# if storage/compute, use bind anonymously
bind_anonymous = True
return {
'platform::ldap::params::ldapserver_remote': ldapserver_remote,
'platform::ldap::params::ldapserver_host': ldapserver_host,
'platform::ldap::params::bind_anonymous': bind_anonymous,
}
# Rest of the configuration is required only for controller hosts
if host.hostname == constants.CONTROLLER_0_HOSTNAME:
server_id = '001'
provider_uri = 'ldap://%s' % constants.CONTROLLER_1_HOSTNAME
elif host.hostname == constants.CONTROLLER_1_HOSTNAME:
server_id = '002'
provider_uri = 'ldap://%s' % constants.CONTROLLER_0_HOSTNAME
else:
raise Exception("unknown controller hostname {}".format(
host.hostname))
return {
'platform::ldap::params::server_id': server_id,
'platform::ldap::params::provider_uri': provider_uri,
'platform::ldap::params::ldapserver_remote': ldapserver_remote,
'platform::ldap::params::ldapserver_host': ldapserver_host,
'platform::ldap::params::bind_anonymous': bind_anonymous,
}
def get_service_config(self, service):
configs = self.context.setdefault('_service_configs', {})
if service not in configs:
configs[service] = self._get_service(service)
return configs[service]