Simplify LDAPUpdater

- drop unused dm_password and ldapi arguments
- remove online feature that was never implemented
- allow passing of api object that is used to populate substitution
  dictionary
- simplify substitution dictionary updates
- remove unused instances vars

Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Christian Heimes
2020-09-15 11:25:30 +02:00
committed by Rob Crittenden
parent 87cf2a3c78
commit 99a40cbbe9
10 changed files with 64 additions and 113 deletions

View File

@@ -673,10 +673,6 @@ class CAInstance(DogtagInstance):
self._ldap_update(
[paths.CA_TOPOLOGY_ULDIF],
basedir=None,
sub_dict={
'SUFFIX': api.env.basedn,
'FQDN': self.fqdn,
}
)
def __disable_nonce(self):
@@ -1361,13 +1357,7 @@ class CAInstance(DogtagInstance):
"Did not find any lightweight CAs; nothing to track")
def __dogtag10_migration(self):
self._ldap_update(
['50-dogtag10-migration.update'],
sub_dict={
'SUFFIX': api.env.basedn,
'FQDN': self.fqdn,
}
)
self._ldap_update(['50-dogtag10-migration.update'])
def is_crlgen_enabled(self):
"""Check if the local CA instance is generating CRL

View File

@@ -142,10 +142,7 @@ class LDAPUpdater_NonUpgrade(LDAPUpdater):
options.schema_files,
ldapi=True) or modified
ld = LDAPUpdate(
sub_dict={},
ldapi=True)
ld = LDAPUpdate()
if not self.files:
self.files = ld.get_all_files(UPDATES_DIR)

View File

@@ -29,8 +29,8 @@ import sys
import uuid
import time
import os
import pwd
import fnmatch
import warnings
import six
@@ -134,28 +134,33 @@ def safe_output(attr, values):
return values
_sentinel = object()
class LDAPUpdate:
action_keywords = [
action_keywords = {
"default", "add", "remove", "only", "onlyifexist", "deleteentry",
"replace", "addifnew", "addifexist"
]
}
index_suffix = DN(
('cn', 'index'), ('cn', 'userRoot'), ('cn', 'ldbm database'),
('cn', 'plugins'), ('cn', 'config')
)
def __init__(self, dm_password=None, sub_dict=None,
online=True, ldapi=False):
def __init__(self, dm_password=_sentinel, sub_dict=None,
online=_sentinel, ldapi=_sentinel, api=api):
'''
:parameters:
dm_password
Directory Manager password
deprecated and no longer used
sub_dict
substitution dictionary
online
Do an online LDAP update or use an experimental LDIF updater
deprecated and no longer used
ldapi
Bind using ldapi. This assumes autobind is enabled.
deprecated and no longer used
api
bootstrapped API object (for configuration)
Data Structure Example:
-----------------------
@@ -260,82 +265,49 @@ class LDAPUpdate:
update format.
'''
if any(arg is not _sentinel for arg in (dm_password, online, ldapi)):
warnings.warn(
"dm_password, online, and ldapi arguments are deprecated",
DeprecationWarning,
stacklevel=2
)
self.sub_dict = sub_dict if sub_dict is not None else {}
self.dm_password = dm_password
self.conn = None
self.modified = False
self.online = online
self.ldapi = ldapi
self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
self.realm = None
self.socket_name = (
paths.SLAPD_INSTANCE_SOCKET_TEMPLATE %
api.env.realm.replace('.', '-')
)
suffix = None
self.ldapuri = ipaldap.realm_to_ldapi_uri(api.env.realm)
if self.sub_dict.get("REALM"):
self.realm = self.sub_dict["REALM"]
else:
self.realm = api.env.realm
suffix = ipautil.realm_to_suffix(self.realm) if self.realm else None
self.ldapuri = ipaldap.realm_to_ldapi_uri(self.realm)
if suffix is not None:
assert isinstance(suffix, DN)
fqdn = installutils.get_fqdn()
if fqdn is None:
raise RuntimeError("Unable to determine hostname")
if not self.sub_dict.get("REALM") and self.realm is not None:
self.sub_dict["REALM"] = self.realm
if not self.sub_dict.get("FQDN"):
self.sub_dict["FQDN"] = fqdn
if not self.sub_dict.get("DOMAIN"):
self.sub_dict["DOMAIN"] = api.env.domain
if not self.sub_dict.get("SUFFIX") and suffix is not None:
self.sub_dict["SUFFIX"] = suffix
if not self.sub_dict.get("ESCAPED_SUFFIX"):
self.sub_dict["ESCAPED_SUFFIX"] = str(suffix)
if not self.sub_dict.get("LIBARCH"):
self.sub_dict["LIBARCH"] = paths.LIBARCH
if not self.sub_dict.get("TIME"):
self.sub_dict["TIME"] = int(time.time())
if not self.sub_dict.get("MIN_DOMAIN_LEVEL"):
self.sub_dict["MIN_DOMAIN_LEVEL"] = str(constants.MIN_DOMAIN_LEVEL)
if not self.sub_dict.get("MAX_DOMAIN_LEVEL"):
self.sub_dict["MAX_DOMAIN_LEVEL"] = str(constants.MAX_DOMAIN_LEVEL)
if not self.sub_dict.get("STRIP_ATTRS"):
self.sub_dict["STRIP_ATTRS"] = "%s" % (
" ".join(constants.REPL_AGMT_STRIP_ATTRS),)
if not self.sub_dict.get("EXCLUDES"):
self.sub_dict["EXCLUDES"] = "(objectclass=*) $ EXCLUDE %s" % (
" ".join(constants.REPL_AGMT_EXCLUDES),)
if not self.sub_dict.get("TOTAL_EXCLUDES"):
self.sub_dict["TOTAL_EXCLUDES"] = "(objectclass=*) $ EXCLUDE " + \
default_sub = dict(
REALM=api.env.realm,
DOMAIN=api.env.domain,
SUFFIX=api.env.basedn,
ESCAPED_SUFFIX=str(api.env.basedn),
FQDN=api.env.host,
LIBARCH=paths.LIBARCH,
TIME=int(time.time()),
MIN_DOMAIN_LEVEL=str(constants.MIN_DOMAIN_LEVEL),
MAX_DOMAIN_LEVEL=str(constants.MAX_DOMAIN_LEVEL),
STRIP_ATTRS=" ".join(constants.REPL_AGMT_STRIP_ATTRS),
EXCLUDES="(objectclass=*) $ EXCLUDE %s" % (
" ".join(constants.REPL_AGMT_EXCLUDES)
),
TOTAL_EXCLUDES="(objectclass=*) $ EXCLUDE %s" % (
" ".join(constants.REPL_AGMT_TOTAL_EXCLUDES)
if not self.sub_dict.get("SELINUX_USERMAP_DEFAULT"):
self.sub_dict["SELINUX_USERMAP_DEFAULT"] = \
platformconstants.SELINUX_USERMAP_DEFAULT
if not self.sub_dict.get("SELINUX_USERMAP_ORDER"):
self.sub_dict["SELINUX_USERMAP_ORDER"] = \
platformconstants.SELINUX_USERMAP_ORDER
if "FIPS" not in self.sub_dict:
self.sub_dict["FIPS"] = '#' if tasks.is_fips_enabled() else ''
),
SELINUX_USERMAP_DEFAULT=platformconstants.SELINUX_USERMAP_DEFAULT,
SELINUX_USERMAP_ORDER=platformconstants.SELINUX_USERMAP_ORDER,
FIPS="#" if tasks.is_fips_enabled() else "",
)
for k, v in default_sub.items():
self.sub_dict.setdefault(k, v)
self.api = create_api(mode=None)
self.api.bootstrap(in_server=True,
context='updates',
confdir=paths.ETC_IPA,
ldap_uri=self.ldapuri)
self.api.bootstrap(
in_server=True,
context='updates',
confdir=paths.ETC_IPA,
ldap_uri=self.ldapuri
)
self.api.finalize()
if online:
# Try out the connection/password
# (This will raise if the server is not available)
self.create_connection()
self.close_connection()
else:
raise RuntimeError("Offline updates are not supported.")
def _template_str(self, s):
try:
@@ -913,13 +885,11 @@ class LDAPUpdate:
self.create_connection()
def create_connection(self):
if self.online:
if self.conn is None:
self.api.Backend.ldap2.connect(
time_limit=UPDATE_SEARCH_TIME_LIMIT,
size_limit=0)
self.conn = self.api.Backend.ldap2
else:
raise RuntimeError("Offline updates are not supported.")
def _run_updates(self, all_updates):
index_attributes = set()

View File

@@ -32,10 +32,7 @@ class update_ca_topology(Updater):
logger.debug("CA is not configured on this host")
return False, []
ld = ldapupdate.LDAPUpdate(ldapi=True, sub_dict={
'SUFFIX': self.api.env.basedn,
'FQDN': self.api.env.host,
})
ld = ldapupdate.LDAPUpdate(api=self.api)
ld.update([paths.CA_TOPOLOGY_ULDIF])

View File

@@ -67,7 +67,7 @@ class update_nis_configuration(Updater):
True)
# bug is effective run update to recreate missing maps
ld = LDAPUpdate(sub_dict={}, ldapi=True)
ld = LDAPUpdate(api=self.api)
ld.update([paths.NIS_ULDIF])
def execute(self, **options):
@@ -86,7 +86,7 @@ class update_nis_configuration(Updater):
self.__recover_from_missing_maps(ldap)
logger.debug("Executing NIS Server update")
ld = LDAPUpdate(sub_dict={}, ldapi=True)
ld = LDAPUpdate(api=self.api)
ld.update([paths.NIS_UPDATE_ULDIF])
return False, ()

View File

@@ -313,7 +313,6 @@ class Service:
self.keytab_user = service_user
self.dm_password = None # silence pylint
self.promote = False
self.sub_dict = None
@property
def principal(self):
@@ -325,22 +324,20 @@ class Service:
kerberos.Principal(
(self.service_prefix, self.fqdn), realm=self.realm))
def _ldap_update(
self, filenames, *, basedir=paths.UPDATES_DIR, sub_dict=None
):
def _ldap_update(self, filenames, *, basedir=paths.UPDATES_DIR):
"""Apply update ldif files
Note: Additional substitution must be added to LDAPUpdate() to ensure
that ipa-ldap-updater is able to handle all update files as well.
:param filenames: list of file names
:param basedir: base directory for files (default: UPDATES_DIR)
:param sub_dict: substitution dict (defaults to self.sub_dict)
:return: modified state
"""
assert isinstance(filenames, (list, tuple))
if sub_dict is None:
sub_dict = self.sub_dict
if basedir is not None:
filenames = [os.path.join(basedir, fname) for fname in filenames]
ld = LDAPUpdate(sub_dict=sub_dict)
ld = LDAPUpdate(api=self.api)
# assume that caller supplies files in correct order
return ld.update(filenames, ordered=False)

View File

@@ -269,7 +269,7 @@ class IPAUpgrade(service.Service):
def __upgrade(self):
try:
ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True)
ld = ldapupdate.LDAPUpdate(api=self.api)
if len(self.files) == 0:
self.files = ld.get_all_files(ldapupdate.UPDATES_DIR)
self.modified = (ld.update(self.files) or self.modified)