2016-10-18 03:16:29 -05:00
|
|
|
#
|
|
|
|
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
|
|
|
|
#
|
|
|
|
|
2017-05-23 11:35:57 -05:00
|
|
|
import logging
|
2016-10-18 03:16:29 -05:00
|
|
|
import time
|
|
|
|
import ldap
|
|
|
|
|
|
|
|
from ipalib.plugable import Registry
|
|
|
|
from ipalib import errors
|
|
|
|
from ipalib import Updater
|
|
|
|
from ipapython.dn import DN
|
|
|
|
|
2017-05-23 11:35:57 -05:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2016-10-18 03:16:29 -05:00
|
|
|
register = Registry()
|
|
|
|
|
|
|
|
|
|
|
|
@register()
|
|
|
|
class update_dna_shared_config(Updater):
|
|
|
|
def execute(self, **options):
|
|
|
|
method = options.get('method', "SASL/GSSAPI")
|
|
|
|
protocol = options.get('protocol', "LDAP")
|
|
|
|
|
|
|
|
dna_bind_method = "dnaRemoteBindMethod"
|
|
|
|
dna_conn_protocol = "dnaRemoteConnProtocol"
|
|
|
|
dna_plugin = DN(('cn', 'Distributed Numeric Assignment Plugin'),
|
|
|
|
('cn', 'plugins'),
|
|
|
|
('cn', 'config'))
|
|
|
|
dna_config_base = DN(('cn', 'posix IDs'), dna_plugin)
|
|
|
|
|
|
|
|
conn = self.api.Backend.ldap2
|
|
|
|
|
|
|
|
# Check the plugin is enabled else it is useless to update
|
|
|
|
# the shared entry
|
|
|
|
try:
|
|
|
|
entry = conn.get_entry(dna_plugin)
|
|
|
|
if entry.single_value.get('nsslapd-pluginenabled') == 'off':
|
|
|
|
return False, ()
|
|
|
|
except errors.NotFound:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.error("Could not find DNA plugin entry: %s",
|
|
|
|
dna_config_base)
|
2016-10-18 03:16:29 -05:00
|
|
|
return False, ()
|
|
|
|
|
|
|
|
try:
|
|
|
|
entry = conn.get_entry(dna_config_base)
|
|
|
|
except errors.NotFound:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.error("Could not find DNA config entry: %s",
|
|
|
|
dna_config_base)
|
2016-10-18 03:16:29 -05:00
|
|
|
return False, ()
|
|
|
|
|
|
|
|
sharedcfgdn = entry.single_value.get("dnaSharedCfgDN")
|
|
|
|
if sharedcfgdn is not None:
|
|
|
|
sharedcfgdn = DN(sharedcfgdn)
|
|
|
|
else:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.error(
|
|
|
|
"Could not find DNA shared config DN in entry: %s",
|
2016-10-18 03:16:29 -05:00
|
|
|
dna_config_base)
|
|
|
|
return False, ()
|
|
|
|
|
|
|
|
#
|
|
|
|
# Update the shared config entry related to that host
|
|
|
|
#
|
|
|
|
# If the shared config entry already exists (like upgrade)
|
|
|
|
# the update occurs immediately without sleep.
|
|
|
|
#
|
|
|
|
# If the shared config entry does not exist (fresh install)
|
|
|
|
# DS server waits for 30s after its startup to create it.
|
|
|
|
# Startup likely occurred few sec before this function is
|
|
|
|
# called so this loop will wait for 30s max.
|
|
|
|
#
|
|
|
|
# In case the server is not able to create the entry
|
|
|
|
# The loop gives a grace period of 60s before logging
|
|
|
|
# the failure to update the shared config entry and return
|
|
|
|
#
|
|
|
|
max_wait = 30
|
|
|
|
fqdn = self.api.env.host
|
|
|
|
for _i in range(0, max_wait + 1):
|
|
|
|
try:
|
|
|
|
entries = conn.get_entries(
|
|
|
|
sharedcfgdn, scope=ldap.SCOPE_ONELEVEL,
|
|
|
|
filter='dnaHostname=%s' % fqdn
|
|
|
|
)
|
|
|
|
break
|
|
|
|
except errors.NotFound:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.debug(
|
2016-10-18 03:16:29 -05:00
|
|
|
"Unable to find DNA shared config entry for "
|
2017-05-23 11:35:57 -05:00
|
|
|
"dnaHostname=%s (under %s) so far. Retry in 2 sec.",
|
|
|
|
fqdn, sharedcfgdn
|
2016-10-18 03:16:29 -05:00
|
|
|
)
|
|
|
|
time.sleep(2)
|
|
|
|
else:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.error(
|
|
|
|
"Could not get dnaHostname entries in %s seconds",
|
|
|
|
max_wait * 2
|
2016-10-18 03:16:29 -05:00
|
|
|
)
|
|
|
|
return False, ()
|
|
|
|
|
|
|
|
# If there are several entries, all of them will be updated
|
|
|
|
# just log a debug msg. This is likely the result of #5510
|
|
|
|
if len(entries) != 1:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.debug(
|
|
|
|
"%d entries dnaHostname=%s under %s. One expected",
|
|
|
|
len(entries), fqdn, sharedcfgdn
|
2016-10-18 03:16:29 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
# time to set the bind method and the protocol in the
|
|
|
|
# shared config entries
|
|
|
|
for entry in entries:
|
|
|
|
update = False
|
|
|
|
if entry.single_value.get(dna_bind_method) != method:
|
|
|
|
entry[dna_bind_method] = method
|
|
|
|
update = True
|
|
|
|
|
|
|
|
if entry.single_value.get(dna_conn_protocol) != protocol:
|
|
|
|
entry[dna_conn_protocol] = protocol
|
|
|
|
update = True
|
|
|
|
|
|
|
|
if update:
|
|
|
|
try:
|
|
|
|
conn.update_entry(entry)
|
|
|
|
except Exception as e:
|
2017-05-23 11:35:57 -05:00
|
|
|
logger.error(
|
2016-10-18 03:16:29 -05:00
|
|
|
"Failed to set SASL/GSSAPI bind method/protocol "
|
2017-05-23 11:35:57 -05:00
|
|
|
"in entry %s: %s", entry, e
|
2016-10-18 03:16:29 -05:00
|
|
|
)
|
|
|
|
# no restart, no update
|
|
|
|
return False, ()
|