Imported Upstream version 4.3.1
This commit is contained in:
BIN
ipaserver/install/plugins/__init__.pyc
Normal file
BIN
ipaserver/install/plugins/__init__.pyc
Normal file
Binary file not shown.
@@ -17,23 +17,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython.dn import DN
|
||||
from ipapython.ipa_log_manager import *
|
||||
from ipapython import sysrestore
|
||||
from ipaserver.install import installutils
|
||||
from ipaserver.install import sysupgrade
|
||||
from ipaserver.install.adtrustinstance import (
|
||||
ADTRUSTInstance, map_Guests_to_nobody)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
DEFAULT_ID_RANGE_SIZE = 200000
|
||||
|
||||
|
||||
@register()
|
||||
class update_default_range(Updater):
|
||||
"""
|
||||
Create default ID range for upgraded servers.
|
||||
@@ -45,12 +39,11 @@ class update_default_range(Updater):
|
||||
dn = DN(self.api.env.container_ranges, self.api.env.basedn)
|
||||
search_filter = "objectclass=ipaDomainIDRange"
|
||||
try:
|
||||
ldap.find_entries(search_filter, [], dn)
|
||||
(entries, truncated) = ldap.find_entries(search_filter, [], dn)
|
||||
except errors.NotFound:
|
||||
pass
|
||||
else:
|
||||
logger.debug("default_range: ipaDomainIDRange entry found, skip "
|
||||
"plugin")
|
||||
root_logger.debug("default_range: ipaDomainIDRange entry found, skip plugin")
|
||||
return False, []
|
||||
|
||||
dn = DN(('cn', 'admins'), self.api.env.container_group,
|
||||
@@ -58,8 +51,8 @@ class update_default_range(Updater):
|
||||
try:
|
||||
admins_entry = ldap.get_entry(dn, ['gidnumber'])
|
||||
except errors.NotFound:
|
||||
logger.error("default_range: No local ID range and no admins "
|
||||
"group found. Cannot create default ID range")
|
||||
root_logger.error("default_range: No local ID range and no admins "
|
||||
"group found. Cannot create default ID range")
|
||||
return False, []
|
||||
|
||||
id_range_base_id = admins_entry['gidnumber'][0]
|
||||
@@ -91,10 +84,10 @@ class update_default_range(Updater):
|
||||
search_filter = "objectclass=dnaSharedConfig"
|
||||
attrs = ['dnaHostname', 'dnaRemainingValues']
|
||||
try:
|
||||
(entries, _truncated) = ldap.find_entries(search_filter, attrs, dn)
|
||||
(entries, truncated) = ldap.find_entries(search_filter, attrs, dn)
|
||||
except errors.NotFound:
|
||||
logger.warning("default_range: no dnaSharedConfig object found. "
|
||||
"Cannot check default range size.")
|
||||
root_logger.warning("default_range: no dnaSharedConfig object found. "
|
||||
"Cannot check default range size.")
|
||||
else:
|
||||
masters = set()
|
||||
remaining_values_sum = 0
|
||||
@@ -106,9 +99,8 @@ class update_default_range(Updater):
|
||||
try:
|
||||
remaining_values = int(remaining_values)
|
||||
except ValueError:
|
||||
logger.warning("default_range: could not parse "
|
||||
"remaining values from '%s'",
|
||||
remaining_values)
|
||||
root_logger.warning("default_range: could not parse "
|
||||
"remaining values from '%s'", remaining_values)
|
||||
continue
|
||||
else:
|
||||
remaining_values_sum += remaining_values
|
||||
@@ -124,12 +116,11 @@ class update_default_range(Updater):
|
||||
' RANGE_SIZE = (--idmax) - (--idstart) + 1'
|
||||
]
|
||||
|
||||
logger.error("default_range: %s", "\n".join(msg))
|
||||
root_logger.error("default_range: %s", "\n".join(msg))
|
||||
|
||||
return False, [update]
|
||||
|
||||
|
||||
@register()
|
||||
class update_default_trust_view(Updater):
|
||||
"""
|
||||
Create Default Trust View for upgraded servers.
|
||||
@@ -152,7 +143,7 @@ class update_default_trust_view(Updater):
|
||||
|
||||
# First, see if trusts are enabled on the server
|
||||
if not self.api.Command.adtrust_is_enabled()['result']:
|
||||
logger.debug('AD Trusts are not enabled on this server')
|
||||
self.log.debug('AD Trusts are not enabled on this server')
|
||||
return False, []
|
||||
|
||||
# Second, make sure the Default Trust View does not exist yet
|
||||
@@ -161,7 +152,7 @@ class update_default_trust_view(Updater):
|
||||
except errors.NotFound:
|
||||
pass
|
||||
else:
|
||||
logger.debug('Default Trust View already present on this server')
|
||||
self.log.debug('Default Trust View already present on this server')
|
||||
return False, []
|
||||
|
||||
# We have a server with AD trust support without Default Trust View.
|
||||
@@ -175,7 +166,6 @@ class update_default_trust_view(Updater):
|
||||
return False, [update]
|
||||
|
||||
|
||||
@register()
|
||||
class update_sigden_extdom_broken_config(Updater):
|
||||
"""Fix configuration of sidgen and extdom plugins
|
||||
|
||||
@@ -206,7 +196,7 @@ class update_sigden_extdom_broken_config(Updater):
|
||||
try:
|
||||
entry = ldap.get_entry(dn, attrs_list=[basedn_attr])
|
||||
except errors.NotFound:
|
||||
logger.debug("configuration for %s not found, skipping", dn)
|
||||
self.log.debug("configuration for %s not found, skipping", dn)
|
||||
else:
|
||||
configured_suffix = entry.single_value.get(basedn_attr)
|
||||
if configured_suffix is None:
|
||||
@@ -218,19 +208,19 @@ class update_sigden_extdom_broken_config(Updater):
|
||||
elif configured_suffix == "$SUFFIX":
|
||||
# configured value is wrong, fix it
|
||||
entry.single_value[basedn_attr] = str(self.api.env.basedn)
|
||||
logger.debug("updating attribute %s of %s to correct "
|
||||
"value %s",
|
||||
basedn_attr, dn, self.api.env.basedn)
|
||||
self.log.debug("updating attribute %s of %s to correct "
|
||||
"value %s", basedn_attr, dn,
|
||||
self.api.env.basedn)
|
||||
ldap.update_entry(entry)
|
||||
modified = True
|
||||
else:
|
||||
logger.debug("configured basedn for %s is okay", dn)
|
||||
self.log.debug("configured basedn for %s is okay", dn)
|
||||
|
||||
return modified
|
||||
|
||||
def execute(self, **options):
|
||||
if sysupgrade.get_upgrade_state('sidgen', 'config_basedn_updated'):
|
||||
logger.debug("Already done, skipping")
|
||||
self.log.debug("Already done, skipping")
|
||||
return False, ()
|
||||
|
||||
restart = False
|
||||
@@ -242,7 +232,6 @@ class update_sigden_extdom_broken_config(Updater):
|
||||
return restart, ()
|
||||
|
||||
|
||||
@register()
|
||||
class update_sids(Updater):
|
||||
"""SIDs may be not created properly if bug with wrong configuration for
|
||||
sidgen and extdom plugins is effective
|
||||
@@ -256,7 +245,7 @@ class update_sids(Updater):
|
||||
ldap = self.api.Backend.ldap2
|
||||
|
||||
if sysupgrade.get_upgrade_state('sidgen', 'update_sids') is not True:
|
||||
logger.debug("SIDs do not need to be generated")
|
||||
self.log.debug("SIDs do not need to be generated")
|
||||
return False, ()
|
||||
|
||||
# check if IPA domain for AD trust has been created, and if we need to
|
||||
@@ -270,8 +259,8 @@ class update_sids(Updater):
|
||||
try:
|
||||
entry = ldap.get_entry(domain_IPA_AD_dn, attrs_list=[attr_name])
|
||||
except errors.NotFound:
|
||||
logger.debug("IPA domain object %s is not configured",
|
||||
domain_IPA_AD_dn)
|
||||
self.log.debug("IPA domain object %s is not configured",
|
||||
domain_IPA_AD_dn)
|
||||
sysupgrade.set_upgrade_state('sidgen', 'update_sids', False)
|
||||
return False, ()
|
||||
else:
|
||||
@@ -292,9 +281,9 @@ class update_sids(Updater):
|
||||
try:
|
||||
ldap.add_entry(task_entry)
|
||||
except errors.DuplicateEntry:
|
||||
logger.debug("sidgen task already created")
|
||||
self.log.debug("sidgen task already created")
|
||||
else:
|
||||
logger.debug("sidgen task has been created")
|
||||
self.log.debug("sidgen task has been created")
|
||||
|
||||
# we have to check all trusts domains which may been affected by the
|
||||
# bug. Symptom is missing 'ipaNTSecurityIdentifier' attribute
|
||||
@@ -313,11 +302,11 @@ class update_sids(Updater):
|
||||
pass
|
||||
else:
|
||||
if truncated:
|
||||
logger.warning("update_sids: Search results were truncated")
|
||||
self.log.warning("update_sids: Search results were truncated")
|
||||
|
||||
for entry in trust_domain_entries:
|
||||
domain = entry.single_value["cn"]
|
||||
logger.error(
|
||||
self.log.error(
|
||||
"Your trust to %s is broken. Please re-create it by "
|
||||
"running 'ipa trust-add' again.", domain)
|
||||
|
||||
@@ -325,78 +314,7 @@ class update_sids(Updater):
|
||||
return False, ()
|
||||
|
||||
|
||||
@register()
|
||||
class update_tdo_gidnumber(Updater):
|
||||
"""
|
||||
Create a gidNumber attribute for Trusted Domain Objects.
|
||||
|
||||
The value is taken from the fallback group defined in cn=Default SMB Group.
|
||||
"""
|
||||
def execute(self, **options):
|
||||
ldap = self.api.Backend.ldap2
|
||||
|
||||
# First, see if trusts are enabled on the server
|
||||
if not self.api.Command.adtrust_is_enabled()['result']:
|
||||
logger.debug('AD Trusts are not enabled on this server')
|
||||
return False, []
|
||||
|
||||
# Read the gidnumber of the fallback group
|
||||
dn = DN(('cn', ADTRUSTInstance.FALLBACK_GROUP_NAME),
|
||||
self.api.env.container_group,
|
||||
self.api.env.basedn)
|
||||
|
||||
try:
|
||||
entry = ldap.get_entry(dn, ['gidnumber'])
|
||||
gidNumber = entry.get('gidnumber')
|
||||
except errors.NotFound:
|
||||
logger.error("%s not found",
|
||||
ADTRUSTInstance.FALLBACK_GROUP_NAME)
|
||||
return False, ()
|
||||
|
||||
if not gidNumber:
|
||||
logger.error("%s does not have a gidnumber",
|
||||
ADTRUSTInstance.FALLBACK_GROUP_NAME)
|
||||
return False, ()
|
||||
|
||||
# For each trusted domain object, add gidNumber
|
||||
try:
|
||||
tdos = ldap.get_entries(
|
||||
DN(self.api.env.container_adtrusts, self.api.env.basedn),
|
||||
scope=ldap.SCOPE_ONELEVEL,
|
||||
filter="(objectclass=ipaNTTrustedDomain)",
|
||||
attrs_list=['gidnumber'])
|
||||
for tdo in tdos:
|
||||
# if the trusted domain object does not contain gidnumber,
|
||||
# add the default fallback group gidnumber
|
||||
if not tdo.get('gidnumber'):
|
||||
try:
|
||||
tdo['gidnumber'] = gidNumber
|
||||
ldap.update_entry(tdo)
|
||||
logger.debug("Added gidnumber %s to %s",
|
||||
gidNumber, tdo.dn)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"Failed to add gidnumber to %s", tdo.dn)
|
||||
|
||||
except errors.NotFound:
|
||||
logger.debug("No trusted domain object to update")
|
||||
return False, ()
|
||||
|
||||
return False, ()
|
||||
|
||||
|
||||
@register()
|
||||
class update_mapping_Guests_to_nobody(Updater):
|
||||
"""
|
||||
Map BUILTIN\\Guests group to nobody
|
||||
|
||||
Samba 4.9 became more strict on availability of builtin Guests group
|
||||
"""
|
||||
def execute(self, **options):
|
||||
# First, see if trusts are enabled on the server
|
||||
if not self.api.Command.adtrust_is_enabled()['result']:
|
||||
logger.debug('AD Trusts are not enabled on this server')
|
||||
return False, []
|
||||
|
||||
map_Guests_to_nobody()
|
||||
return False, []
|
||||
api.register(update_default_range)
|
||||
api.register(update_default_trust_view)
|
||||
api.register(update_sids)
|
||||
api.register(update_sigden_extdom_broken_config)
|
||||
|
||||
@@ -17,20 +17,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from ipaserver.install import cainstance
|
||||
from ipaserver.install import installutils, certs, cainstance
|
||||
from ipalib import errors
|
||||
from ipalib import Updater
|
||||
from ipalib.install import certmonger
|
||||
from ipalib.plugable import Registry
|
||||
from ipapython import certmonger
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython.dn import DN
|
||||
from ipapython import directivesetter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
@@ -41,15 +34,14 @@ class update_ca_renewal_master(Updater):
|
||||
"""
|
||||
|
||||
def execute(self, **options):
|
||||
ca = cainstance.CAInstance(self.api.env.realm)
|
||||
ca = cainstance.CAInstance(self.api.env.realm, certs.NSS_DIR)
|
||||
if not ca.is_configured():
|
||||
logger.debug("CA is not configured on this host")
|
||||
self.debug("CA is not configured on this host")
|
||||
return False, []
|
||||
|
||||
ldap = self.api.Backend.ldap2
|
||||
base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
|
||||
self.api.env.basedn)
|
||||
dn = DN(('cn', 'CA'), ('cn', self.api.env.host), base_dn)
|
||||
filter = '(&(cn=CA)(ipaConfigString=caRenewalMaster))'
|
||||
try:
|
||||
entries = ldap.get_entries(base_dn=base_dn, filter=filter,
|
||||
@@ -57,40 +49,21 @@ class update_ca_renewal_master(Updater):
|
||||
except errors.NotFound:
|
||||
pass
|
||||
else:
|
||||
logger.debug("found CA renewal master %s", entries[0].dn[1].value)
|
||||
|
||||
master = False
|
||||
updates = []
|
||||
|
||||
for entry in entries:
|
||||
if entry.dn == dn:
|
||||
master = True
|
||||
continue
|
||||
|
||||
updates.append({
|
||||
'dn': entry.dn,
|
||||
'updates': [
|
||||
dict(action='remove', attr='ipaConfigString',
|
||||
value='caRenewalMaster')
|
||||
],
|
||||
})
|
||||
|
||||
if master:
|
||||
return False, updates
|
||||
else:
|
||||
return False, []
|
||||
self.debug("found CA renewal master %s", entries[0].dn[1].value)
|
||||
return False, []
|
||||
|
||||
criteria = {
|
||||
'cert-file': paths.RA_AGENT_PEM,
|
||||
'cert-database': paths.HTTPD_ALIAS_DIR,
|
||||
'cert-nickname': 'ipaCert',
|
||||
}
|
||||
request_id = certmonger.get_request_id(criteria)
|
||||
if request_id is not None:
|
||||
logger.debug("found certmonger request for RA cert")
|
||||
self.debug("found certmonger request for ipaCert")
|
||||
|
||||
ca_name = certmonger.get_request_value(request_id, 'ca-name')
|
||||
if ca_name is None:
|
||||
logger.warning(
|
||||
"certmonger request for RA cert is missing ca_name, "
|
||||
self.warning(
|
||||
"certmonger request for ipaCert is missing ca_name, "
|
||||
"assuming local CA is renewal slave")
|
||||
return False, []
|
||||
ca_name = ca_name.strip()
|
||||
@@ -102,14 +75,14 @@ class update_ca_renewal_master(Updater):
|
||||
elif ca_name == 'dogtag-ipa-ca-renew-agent':
|
||||
return False, []
|
||||
else:
|
||||
logger.warning(
|
||||
"certmonger request for RA cert has unknown ca_name '%s', "
|
||||
self.warning(
|
||||
"certmonger request for ipaCert has unknown ca_name '%s', "
|
||||
"assuming local CA is renewal slave", ca_name)
|
||||
return False, []
|
||||
else:
|
||||
logger.debug("certmonger request for RA cert not found")
|
||||
self.debug("certmonger request for ipaCert not found")
|
||||
|
||||
config = directivesetter.get_directive(
|
||||
config = installutils.get_directive(
|
||||
paths.CA_CS_CFG_PATH, 'subsystem.select', '=')
|
||||
|
||||
if config == 'New':
|
||||
@@ -117,11 +90,12 @@ class update_ca_renewal_master(Updater):
|
||||
elif config == 'Clone':
|
||||
return False, []
|
||||
else:
|
||||
logger.warning(
|
||||
self.warning(
|
||||
"CS.cfg has unknown subsystem.select value '%s', "
|
||||
"assuming local CA is renewal slave", config)
|
||||
return (False, False, [])
|
||||
|
||||
dn = DN(('cn', 'CA'), ('cn', self.api.env.host), base_dn)
|
||||
update = {
|
||||
'dn': dn,
|
||||
'updates': [
|
||||
|
||||
@@ -17,148 +17,20 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
import dns.exception
|
||||
import ldap as _ldap
|
||||
import re
|
||||
import traceback
|
||||
import time
|
||||
|
||||
from ldif import LDIFWriter
|
||||
|
||||
from ipalib import Registry, errors, util
|
||||
from ipalib import api, errors, util
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
from ipapython import dnsutil
|
||||
from ipaserver.install import sysupgrade
|
||||
from ipaserver.install.bindinstance import ensure_dnsserver_container_exists
|
||||
from ipaserver.plugins.dns import dns_container_exists
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
from ipalib.plugins.dns import dns_container_exists
|
||||
from ipapython.ipa_log_manager import *
|
||||
|
||||
|
||||
class DNSUpdater(Updater):
|
||||
backup_dir = u'/var/lib/ipa/backup/'
|
||||
# override backup_filename in subclass, it will be mangled by strftime
|
||||
backup_filename = None
|
||||
|
||||
def __init__(self, api):
|
||||
super(DNSUpdater, self).__init__(api)
|
||||
backup_path = u'%s%s' % (self.backup_dir, self.backup_filename)
|
||||
self.backup_path = time.strftime(backup_path)
|
||||
self._ldif_writer = None
|
||||
self._saved_privileges = set() # store privileges only once
|
||||
self.saved_zone_to_privilege = {}
|
||||
|
||||
def version_update_needed(self, target_version):
|
||||
"""Test if IPA DNS version is smaller than target version."""
|
||||
assert isinstance(target_version, int)
|
||||
|
||||
try:
|
||||
return int(self.api.Command['dnsconfig_show'](
|
||||
all=True)['result']['ipadnsversion'][0]) < target_version
|
||||
except errors.NotFound:
|
||||
# IPA DNS is not configured
|
||||
return False
|
||||
|
||||
@property
|
||||
def ldif_writer(self):
|
||||
if not self._ldif_writer:
|
||||
logger.info('Original zones will be saved in LDIF format in '
|
||||
'%s file', self.backup_path)
|
||||
self._ldif_writer = LDIFWriter(open(self.backup_path, 'w'))
|
||||
return self._ldif_writer
|
||||
|
||||
def backup_zone(self, zone):
|
||||
"""Backup zone object, its records, permissions, and privileges.
|
||||
|
||||
Mapping from zone to privilege (containing zone's permissions)
|
||||
will be stored in saved_zone_to_privilege dict for further usage.
|
||||
"""
|
||||
dn = str(zone['dn'])
|
||||
del zone['dn'] # dn shouldn't be as attribute in ldif
|
||||
self.ldif_writer.unparse(dn, zone)
|
||||
|
||||
ldap = self.api.Backend.ldap2
|
||||
if 'managedBy' in zone:
|
||||
permission = ldap.get_entry(DN(zone['managedBy'][0]))
|
||||
self.ldif_writer.unparse(str(permission.dn), dict(permission.raw))
|
||||
for privilege_dn in permission.get('member', []):
|
||||
# privileges can be shared by multiples zones
|
||||
if privilege_dn not in self._saved_privileges:
|
||||
self._saved_privileges.add(privilege_dn)
|
||||
privilege = ldap.get_entry(privilege_dn)
|
||||
self.ldif_writer.unparse(str(privilege.dn),
|
||||
dict(privilege.raw))
|
||||
|
||||
# remember privileges referened by permission
|
||||
if 'member' in permission:
|
||||
self.saved_zone_to_privilege[
|
||||
zone['idnsname'][0]
|
||||
] = permission['member']
|
||||
|
||||
if 'idnszone' in zone['objectClass']:
|
||||
# raw values are required to store into ldif
|
||||
records = self.api.Command['dnsrecord_find'](zone['idnsname'][0],
|
||||
all=True,
|
||||
raw=True,
|
||||
sizelimit=0)['result']
|
||||
for record in records:
|
||||
if record['idnsname'][0] == u'@':
|
||||
# zone record was saved before
|
||||
continue
|
||||
dn = str(record['dn'])
|
||||
del record['dn']
|
||||
self.ldif_writer.unparse(dn, record)
|
||||
|
||||
|
||||
@register()
|
||||
class update_ipaconfigstring_dnsversion_to_ipadnsversion(Updater):
|
||||
"""
|
||||
IPA <= 4.3.1 used ipaConfigString "DNSVersion 1" on DNS container.
|
||||
This was hard to deal with in API so from IPA 4.3.2 we are using
|
||||
new ipaDNSVersion attribute with integer syntax.
|
||||
Old ipaConfigString is left there for now so if someone accidentally
|
||||
executes upgrade on an old replica again it will not re-upgrade the data.
|
||||
"""
|
||||
def execute(self, **options):
|
||||
ldap = self.api.Backend.ldap2
|
||||
dns_container_dn = DN(self.api.env.container_dns, self.api.env.basedn)
|
||||
try:
|
||||
container_entry = ldap.get_entry(dns_container_dn)
|
||||
except errors.NotFound:
|
||||
# DNS container not found, nothing to upgrade
|
||||
return False, []
|
||||
|
||||
if 'ipadnscontainer' in [
|
||||
o.lower() for o in container_entry['objectclass']
|
||||
]:
|
||||
# version data are already migrated
|
||||
return False, []
|
||||
|
||||
logger.debug('Migrating DNS ipaConfigString to ipaDNSVersion')
|
||||
container_entry['objectclass'].append('ipadnscontainer')
|
||||
version = 0
|
||||
for config_option in container_entry.get("ipaConfigString", []):
|
||||
matched = re.match(r"^DNSVersion\s+(?P<version>\d+)$",
|
||||
config_option, flags=re.I)
|
||||
if matched:
|
||||
version = int(matched.group("version"))
|
||||
else:
|
||||
logger.error(
|
||||
'Failed to parse DNS version from ipaConfigString, '
|
||||
'defaulting to version %s', version)
|
||||
container_entry['ipadnsversion'] = version
|
||||
ldap.update_entry(container_entry)
|
||||
logger.debug('ipaDNSVersion = %s', version)
|
||||
return False, []
|
||||
|
||||
|
||||
@register()
|
||||
class update_dnszones(Updater):
|
||||
"""
|
||||
Update all zones to meet requirements in the new FreeIPA versions
|
||||
@@ -192,7 +64,7 @@ class update_dnszones(Updater):
|
||||
try:
|
||||
zones = self.api.Command.dnszone_find(all=True)['result']
|
||||
except errors.NotFound:
|
||||
logger.debug('No DNS zone to update found')
|
||||
self.log.debug('No DNS zone to update found')
|
||||
return False, []
|
||||
|
||||
for zone in zones:
|
||||
@@ -218,8 +90,9 @@ class update_dnszones(Updater):
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_dnszones)
|
||||
|
||||
|
||||
@register()
|
||||
class update_dns_limits(Updater):
|
||||
"""
|
||||
bind-dyndb-ldap persistent search queries LDAP for all DNS records.
|
||||
@@ -245,13 +118,11 @@ class update_dns_limits(Updater):
|
||||
entry = ldap.get_entry(dns_service_dn, self.limit_attributes)
|
||||
except errors.NotFound:
|
||||
# this host may not have DNS service set
|
||||
logger.debug("DNS: service %s not found, no need to update limits",
|
||||
dns_service_dn)
|
||||
root_logger.debug("DNS: service %s not found, no need to update limits" % dns_service_dn)
|
||||
return False, []
|
||||
|
||||
if all(entry.get(limit.lower(), [None])[0] == self.limit_value for limit in self.limit_attributes):
|
||||
logger.debug("DNS: limits for service %s already set",
|
||||
dns_service_dn)
|
||||
root_logger.debug("DNS: limits for service %s already set" % dns_service_dn)
|
||||
# service is already updated
|
||||
return False, []
|
||||
|
||||
@@ -262,15 +133,15 @@ class update_dns_limits(Updater):
|
||||
value=self.limit_value))
|
||||
|
||||
dnsupdate = {'dn': dns_service_dn, 'updates': limit_updates}
|
||||
logger.debug("DNS: limits for service %s will be updated",
|
||||
dns_service_dn)
|
||||
root_logger.debug("DNS: limits for service %s will be updated" % dns_service_dn)
|
||||
|
||||
|
||||
return False, [dnsupdate]
|
||||
|
||||
api.register(update_dns_limits)
|
||||
|
||||
@register()
|
||||
class update_master_to_dnsforwardzones(DNSUpdater):
|
||||
|
||||
class update_master_to_dnsforwardzones(Updater):
|
||||
"""
|
||||
Update all zones to meet requirements in the new FreeIPA versions
|
||||
|
||||
@@ -278,21 +149,35 @@ class update_master_to_dnsforwardzones(DNSUpdater):
|
||||
than none, will be tranformed to forward zones.
|
||||
Original masters zone will be backed up to ldif file.
|
||||
|
||||
This should be applied only once,
|
||||
and only if original version was lower than 4.0
|
||||
This should be applied only once, and only if original version was lower than 4.0
|
||||
"""
|
||||
backup_filename = u'dns-master-to-forward-zones-%Y-%m-%d-%H-%M-%S.ldif'
|
||||
backup_dir = u'/var/lib/ipa/backup/'
|
||||
backup_filename = u'dns-forward-zones-backup-%Y-%m-%d-%H-%M-%S.ldif'
|
||||
backup_path = u'%s%s' % (backup_dir, backup_filename)
|
||||
|
||||
def execute(self, **options):
|
||||
ldap = self.api.Backend.ldap2
|
||||
# check LDAP if forwardzones already uses new semantics
|
||||
if not self.version_update_needed(target_version=1):
|
||||
# forwardzones already uses new semantics,
|
||||
# no upgrade is required
|
||||
dns_container_dn = DN(self.api.env.container_dns, self.api.env.basedn)
|
||||
try:
|
||||
container_entry = ldap.get_entry(dns_container_dn)
|
||||
except errors.NotFound:
|
||||
# DNS container not found, nothing to upgrade
|
||||
return False, []
|
||||
|
||||
logger.debug('Updating forward zones')
|
||||
for config_option in container_entry.get("ipaConfigString", []):
|
||||
matched = re.match("^DNSVersion\s+(?P<version>\d+)$",
|
||||
config_option, flags=re.I)
|
||||
if matched and int(matched.group("version")) >= 1:
|
||||
# forwardzones already uses new semantics,
|
||||
# no upgrade is required
|
||||
return False, []
|
||||
|
||||
self.log.debug('Updating forward zones')
|
||||
# update the DNSVersion, following upgrade can be executed only once
|
||||
self.api.Command['dnsconfig_mod'](ipadnsversion=1)
|
||||
container_entry.setdefault(
|
||||
'ipaConfigString', []).append(u"DNSVersion 1")
|
||||
ldap.update_entry(container_entry)
|
||||
|
||||
# Updater in IPA version from 4.0 to 4.1.2 doesn't work well, this
|
||||
# should detect if update in past has been executed, and set proper
|
||||
@@ -317,7 +202,7 @@ class update_master_to_dnsforwardzones(DNSUpdater):
|
||||
pass
|
||||
|
||||
if not zones:
|
||||
logger.debug('No DNS zone to update found')
|
||||
self.log.debug('No DNS zone to update found')
|
||||
return False, []
|
||||
|
||||
zones_to_transform = []
|
||||
@@ -332,43 +217,100 @@ class update_master_to_dnsforwardzones(DNSUpdater):
|
||||
zones_to_transform.append(zone)
|
||||
|
||||
if zones_to_transform:
|
||||
logger.info('Zones with specified forwarders with policy '
|
||||
'different than none will be transformed to forward '
|
||||
'zones.')
|
||||
# add time to filename
|
||||
self.backup_path = time.strftime(self.backup_path)
|
||||
|
||||
# DNs of privileges which contain dns managed permissions
|
||||
privileges_to_ldif = set() # store priviledges only once
|
||||
zone_to_privileges = {} # zone: [privileges cn]
|
||||
|
||||
self.log.info('Zones with specified forwarders with policy different'
|
||||
' than none will be transformed to forward zones.')
|
||||
self.log.info('Original zones will be saved in LDIF format in '
|
||||
'%s file' % self.backup_path)
|
||||
try:
|
||||
|
||||
with open(self.backup_path, 'w') as f:
|
||||
writer = LDIFWriter(f)
|
||||
for zone in zones_to_transform:
|
||||
# save backup to ldif
|
||||
try:
|
||||
|
||||
dn = str(zone['dn'])
|
||||
del zone['dn'] # dn shouldn't be as attribute in ldif
|
||||
writer.unparse(dn, zone)
|
||||
|
||||
if 'managedBy' in zone:
|
||||
entry = ldap.get_entry(DN(zone['managedBy'][0]))
|
||||
for privilege_member_dn in entry.get('member', []):
|
||||
privileges_to_ldif.add(privilege_member_dn)
|
||||
writer.unparse(str(entry.dn), dict(entry.raw))
|
||||
|
||||
# privileges where permission is used
|
||||
if entry.get('member'):
|
||||
zone_to_privileges[zone['idnsname'][0]] = entry['member']
|
||||
|
||||
# raw values are required to store into ldif
|
||||
records = self.api.Command['dnsrecord_find'](
|
||||
zone['idnsname'][0],
|
||||
all=True,
|
||||
raw=True,
|
||||
sizelimit=0)['result']
|
||||
for record in records:
|
||||
if record['idnsname'][0] == u'@':
|
||||
# zone record was saved before
|
||||
continue
|
||||
dn = str(record['dn'])
|
||||
del record['dn']
|
||||
writer.unparse(dn, record)
|
||||
|
||||
except Exception as e:
|
||||
self.log.error('Unable to backup zone %s' %
|
||||
zone['idnsname'][0])
|
||||
self.log.error(traceback.format_exc())
|
||||
return False, []
|
||||
|
||||
for privilege_dn in privileges_to_ldif:
|
||||
try:
|
||||
entry = ldap.get_entry(privilege_dn)
|
||||
writer.unparse(str(entry.dn), dict(entry.raw))
|
||||
except Exception as e:
|
||||
self.log.error('Unable to backup privilege %s' %
|
||||
privilege_dn)
|
||||
self.log.error(traceback.format_exc())
|
||||
return False, []
|
||||
|
||||
f.close()
|
||||
except Exception:
|
||||
self.log.error('Unable to create backup file')
|
||||
self.log.error(traceback.format_exc())
|
||||
return False, []
|
||||
|
||||
# update
|
||||
for zone in zones_to_transform:
|
||||
try:
|
||||
self.backup_zone(zone)
|
||||
except Exception:
|
||||
logger.error('Unable to create backup for zone, '
|
||||
'terminating zone upgrade')
|
||||
logger.error("%s", traceback.format_exc())
|
||||
return False, []
|
||||
|
||||
# delete master zone
|
||||
try:
|
||||
self.api.Command['dnszone_del'](zone['idnsname'])
|
||||
except Exception as e:
|
||||
logger.error('Transform to forwardzone terminated: '
|
||||
'removing zone %s failed (%s)',
|
||||
zone['idnsname'][0], e)
|
||||
logger.error("%s", traceback.format_exc())
|
||||
self.log.error('Transform to forwardzone terminated: '
|
||||
'removing zone %s failed (%s)' % (
|
||||
zone['idnsname'][0], e)
|
||||
)
|
||||
self.log.error(traceback.format_exc())
|
||||
continue
|
||||
|
||||
# create forward zone
|
||||
try:
|
||||
kw = {
|
||||
'idnsforwarders': zone.get('idnsforwarders', []),
|
||||
'idnsforwardpolicy': zone.get('idnsforwardpolicy',
|
||||
[u'first'])[0],
|
||||
'skip_overlap_check': True,
|
||||
'idnsforwardpolicy': zone.get('idnsforwardpolicy', [u'first'])[0]
|
||||
}
|
||||
self.api.Command['dnsforwardzone_add'](zone['idnsname'][0], **kw)
|
||||
except Exception:
|
||||
logger.error('Transform to forwardzone terminated: '
|
||||
'creating forwardzone %s failed',
|
||||
zone['idnsname'][0])
|
||||
logger.error("%s", traceback.format_exc())
|
||||
except Exception as e:
|
||||
self.log.error('Transform to forwardzone terminated: creating '
|
||||
'forwardzone %s failed' %
|
||||
zone['idnsname'][0])
|
||||
self.log.error(traceback.format_exc())
|
||||
continue
|
||||
|
||||
# create permission if original zone has one
|
||||
@@ -376,178 +318,37 @@ class update_master_to_dnsforwardzones(DNSUpdater):
|
||||
try:
|
||||
perm_name = self.api.Command['dnsforwardzone_add_permission'](
|
||||
zone['idnsname'][0])['value']
|
||||
except Exception:
|
||||
logger.error('Transform to forwardzone terminated: '
|
||||
'Adding managed by permission to forward '
|
||||
'zone %s failed', zone['idnsname'])
|
||||
logger.error("%s", traceback.format_exc())
|
||||
logger.info('Zone %s was transformed to forward zone '
|
||||
' without managed permissions',
|
||||
zone['idnsname'][0])
|
||||
except Exception as e:
|
||||
self.log.error('Transform to forwardzone terminated: '
|
||||
'Adding managed by permission to forward zone'
|
||||
' %s failed' % zone['idnsname'])
|
||||
self.log.error(traceback.format_exc())
|
||||
self.log.info('Zone %s was transformed to forward zone '
|
||||
' without managed permissions',
|
||||
zone['idnsname'][0])
|
||||
continue
|
||||
|
||||
else:
|
||||
if zone['idnsname'][0] in self.saved_zone_to_privilege:
|
||||
if zone['idnsname'][0] in zone_to_privileges:
|
||||
privileges = [
|
||||
dn[0].value for dn in self.saved_zone_to_privilege[zone['idnsname'][0]]
|
||||
dn[0].value for dn in zone_to_privileges[zone['idnsname'][0]]
|
||||
]
|
||||
try:
|
||||
self.api.Command['permission_add_member'](perm_name,
|
||||
privilege=privileges)
|
||||
except Exception:
|
||||
logger.error('Unable to restore privileges '
|
||||
'for permission %s, for zone %s',
|
||||
perm_name, zone['idnsname'])
|
||||
logger.error("%s", traceback.format_exc())
|
||||
logger.info('Zone %s was transformed to '
|
||||
'forward zone without restored '
|
||||
'privileges',
|
||||
zone['idnsname'][0])
|
||||
except Exception as e:
|
||||
self.log.error('Unable to restore privileges for '
|
||||
'permission %s, for zone %s'
|
||||
% (perm_name, zone['idnsname']))
|
||||
self.log.error(traceback.format_exc())
|
||||
self.log.info('Zone %s was transformed to forward zone'
|
||||
' without restored privileges',
|
||||
zone['idnsname'][0])
|
||||
continue
|
||||
|
||||
logger.debug('Zone %s was sucessfully transformed to forward '
|
||||
'zone',
|
||||
zone['idnsname'][0])
|
||||
self.log.debug('Zone %s was sucessfully transformed to forward zone',
|
||||
zone['idnsname'][0])
|
||||
|
||||
return False, []
|
||||
|
||||
|
||||
@register()
|
||||
class update_dnsforward_emptyzones(DNSUpdater):
|
||||
"""
|
||||
Migrate forward policies which conflict with automatic empty zones
|
||||
(RFC 6303) to use forward policy = only.
|
||||
|
||||
BIND ignores conflicting forwarding configuration
|
||||
when forwarding policy != only.
|
||||
bind-dyndb-ldap 9.0+ will do the same so we have to adjust FreeIPA zones
|
||||
accordingly.
|
||||
"""
|
||||
backup_filename = u'dns-forwarding-empty-zones-%Y-%m-%d-%H-%M-%S.ldif'
|
||||
|
||||
def update_zones(self):
|
||||
try:
|
||||
fwzones = self.api.Command.dnsforwardzone_find(all=True,
|
||||
raw=True)['result']
|
||||
except errors.NotFound:
|
||||
# No forwardzones found, we are done
|
||||
return
|
||||
|
||||
logged_once = False
|
||||
for zone in fwzones:
|
||||
if not (
|
||||
dnsutil.related_to_auto_empty_zone(
|
||||
dnsutil.DNSName(zone.get('idnsname')[0]))
|
||||
and zone.get('idnsforwardpolicy', [u'first'])[0] != u'only'
|
||||
and zone.get('idnsforwarders', []) != []
|
||||
):
|
||||
# this zone does not conflict with automatic empty zone
|
||||
continue
|
||||
|
||||
if not logged_once:
|
||||
logger.info('Forward policy for zones conflicting with '
|
||||
'automatic empty zones will be changed to "only"')
|
||||
logged_once = True
|
||||
|
||||
# backup
|
||||
try:
|
||||
self.backup_zone(zone)
|
||||
except Exception:
|
||||
logger.error('Unable to create backup for zone %s, '
|
||||
'terminating zone upgrade',
|
||||
zone['idnsname'][0])
|
||||
logger.error("%s", traceback.format_exc())
|
||||
continue
|
||||
|
||||
# change forward policy
|
||||
try:
|
||||
self.api.Command['dnsforwardzone_mod'](
|
||||
zone['idnsname'][0],
|
||||
idnsforwardpolicy=u'only'
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error('Forward policy update for zone %s failed '
|
||||
'(%s)', zone['idnsname'][0], e)
|
||||
logger.error("%s", traceback.format_exc())
|
||||
continue
|
||||
|
||||
logger.debug('Zone %s was sucessfully modified to use forward '
|
||||
'policy "only"', zone['idnsname'][0])
|
||||
|
||||
def update_global_ldap_forwarder(self):
|
||||
config = self.api.Command['dnsconfig_show'](all=True,
|
||||
raw=True)['result']
|
||||
if (
|
||||
config.get('idnsforwardpolicy', [u'first'])[0] == u'first'
|
||||
and config.get('idnsforwarders', [])
|
||||
):
|
||||
logger.info('Global forward policy in LDAP for all servers will '
|
||||
'be changed to "only" to avoid conflicts with '
|
||||
'automatic empty zones')
|
||||
self.backup_zone(config)
|
||||
self.api.Command['dnsconfig_mod'](idnsforwardpolicy=u'only')
|
||||
|
||||
def execute(self, **options):
|
||||
# check LDAP if DNS subtree already uses new semantics
|
||||
if not self.version_update_needed(target_version=2):
|
||||
# forwardzones already use new semantics, no upgrade is required
|
||||
return False, []
|
||||
|
||||
logger.debug('Updating forwarding policies in LDAP '
|
||||
'to avoid conflicts with automatic empty zones')
|
||||
# update the DNSVersion, following upgrade can be executed only once
|
||||
self.api.Command['dnsconfig_mod'](ipadnsversion=2)
|
||||
|
||||
self.update_zones()
|
||||
try:
|
||||
if dnsutil.has_empty_zone_addresses(self.api.env.host):
|
||||
self.update_global_ldap_forwarder()
|
||||
except dns.exception.DNSException as ex:
|
||||
logger.error('Skipping update of global DNS forwarder in LDAP: '
|
||||
'Unable to determine if local server is using an '
|
||||
'IP address belonging to an automatic empty zone. '
|
||||
'Consider changing forwarding policy to "only". '
|
||||
'DNS exception: %s', ex)
|
||||
|
||||
return False, []
|
||||
|
||||
|
||||
@register()
|
||||
class update_dnsserver_configuration_into_ldap(DNSUpdater):
|
||||
"""
|
||||
DNS Locations feature requires to have DNS configuration stored in LDAP DB.
|
||||
Create DNS server configuration in LDAP for each old server
|
||||
"""
|
||||
def execute(self, **options):
|
||||
ldap = self.api.Backend.ldap2
|
||||
if sysupgrade.get_upgrade_state('dns', 'server_config_to_ldap'):
|
||||
logger.debug('upgrade is not needed')
|
||||
return False, []
|
||||
|
||||
dns_container_dn = DN(self.api.env.container_dns, self.api.env.basedn)
|
||||
try:
|
||||
ldap.get_entry(dns_container_dn)
|
||||
except errors.NotFound:
|
||||
logger.debug('DNS container not found, nothing to upgrade')
|
||||
sysupgrade.set_upgrade_state('dns', 'server_config_to_ldap', True)
|
||||
return False, []
|
||||
|
||||
result = self.api.Command.server_show(self.api.env.host)['result']
|
||||
if not 'DNS server' in result.get('enabled_role_servrole', []):
|
||||
logger.debug('This server is not DNS server, nothing to upgrade')
|
||||
sysupgrade.set_upgrade_state('dns', 'server_config_to_ldap', True)
|
||||
return False, []
|
||||
|
||||
# create container first, if doesn't exist
|
||||
ensure_dnsserver_container_exists(ldap, self.api)
|
||||
|
||||
try:
|
||||
self.api.Command.dnsserver_add(self.api.env.host)
|
||||
except errors.DuplicateEntry:
|
||||
logger.debug("DNS server configuration already exists "
|
||||
"in LDAP database")
|
||||
else:
|
||||
logger.debug("DNS server configuration has been sucessfully "
|
||||
"created in LDAP database")
|
||||
sysupgrade.set_upgrade_state('dns', 'server_config_to_ldap', True)
|
||||
return False, []
|
||||
api.register(update_master_to_dnsforwardzones)
|
||||
|
||||
@@ -17,20 +17,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
import os
|
||||
import pwd
|
||||
from ipapython import ipaldap
|
||||
from ipaserver.install import replication
|
||||
from ipalib import Registry
|
||||
from ipalib import api
|
||||
from ipalib import Updater
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
EXCLUDE_TEMPLATE = '(objectclass=*) $ EXCLUDE %s'
|
||||
|
||||
|
||||
@register()
|
||||
class update_replica_attribute_lists(Updater):
|
||||
"""
|
||||
Run through all replication agreements and ensure that EXCLUDE list
|
||||
@@ -39,8 +35,8 @@ class update_replica_attribute_lists(Updater):
|
||||
"""
|
||||
|
||||
def execute(self, **options):
|
||||
# We need an LDAPClient connection to the backend
|
||||
logger.debug("Start replication agreement exclude list update task")
|
||||
# We need an IPAdmin connection to the backend
|
||||
self.log.debug("Start replication agreement exclude list update task")
|
||||
conn = self.api.Backend.ldap2
|
||||
|
||||
repl = replication.ReplicationManager(self.api.env.realm,
|
||||
@@ -50,11 +46,11 @@ class update_replica_attribute_lists(Updater):
|
||||
# We need to update only IPA replica agreements, not winsync
|
||||
ipa_replicas = repl.find_ipa_replication_agreements()
|
||||
|
||||
logger.debug("Found %d agreement(s)", len(ipa_replicas))
|
||||
self.log.debug("Found %d agreement(s)", len(ipa_replicas))
|
||||
|
||||
for replica in ipa_replicas:
|
||||
for desc in replica.get('description', []):
|
||||
logger.debug('%s', desc)
|
||||
self.log.debug(desc)
|
||||
|
||||
self._update_attr(repl, replica,
|
||||
'nsDS5ReplicatedAttributeList',
|
||||
@@ -65,7 +61,7 @@ class update_replica_attribute_lists(Updater):
|
||||
self._update_attr(repl, replica,
|
||||
'nsds5ReplicaStripAttrs', replication.STRIP_ATTRS)
|
||||
|
||||
logger.debug("Done updating agreements")
|
||||
self.log.debug("Done updating agreements")
|
||||
|
||||
return False, [] # No restart, no updates
|
||||
|
||||
@@ -85,16 +81,16 @@ class update_replica_attribute_lists(Updater):
|
||||
"""
|
||||
attrlist = replica.single_value.get(attribute)
|
||||
if attrlist is None:
|
||||
logger.debug("Adding %s", attribute)
|
||||
self.log.debug("Adding %s", attribute)
|
||||
|
||||
# Need to add it altogether
|
||||
replica[attribute] = [template % " ".join(values)]
|
||||
|
||||
try:
|
||||
repl.conn.update_entry(replica)
|
||||
logger.debug("Updated")
|
||||
self.log.debug("Updated")
|
||||
except Exception as e:
|
||||
logger.error("Error caught updating replica: %s", str(e))
|
||||
self.log.error("Error caught updating replica: %s", str(e))
|
||||
|
||||
else:
|
||||
attrlist_normalized = attrlist.lower().split()
|
||||
@@ -102,17 +98,19 @@ class update_replica_attribute_lists(Updater):
|
||||
if a.lower() not in attrlist_normalized]
|
||||
|
||||
if missing:
|
||||
logger.debug("%s needs updating (missing: %s)", attribute,
|
||||
', '.join(missing))
|
||||
self.log.debug("%s needs updating (missing: %s)", attribute,
|
||||
', '.join(missing))
|
||||
|
||||
replica[attribute] = [
|
||||
'%s %s' % (attrlist, ' '.join(missing))]
|
||||
|
||||
try:
|
||||
repl.conn.update_entry(replica)
|
||||
logger.debug("Updated %s", attribute)
|
||||
self.log.debug("Updated %s", attribute)
|
||||
except Exception as e:
|
||||
logger.error("Error caught updating %s: %s",
|
||||
attribute, str(e))
|
||||
self.log.error("Error caught updating %s: %s",
|
||||
attribute, str(e))
|
||||
else:
|
||||
logger.debug("%s: No update necessary", attribute)
|
||||
self.log.debug("%s: No update necessary" % attribute)
|
||||
|
||||
api.register(update_replica_attribute_lists)
|
||||
|
||||
@@ -17,19 +17,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython import ipautil
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
@@ -60,8 +54,8 @@ class GenerateUpdateMixin(object):
|
||||
If the input DN doesn't end with old_suffix, log, an raise ValueError.
|
||||
"""
|
||||
if not dn.endswith(old_suffix):
|
||||
logger.error("unable to replace suffix '%s' with '%s' in '%s'",
|
||||
old_suffix, new_suffix, dn)
|
||||
self.error("unable to replace suffix '%s' with '%s' in '%s'",
|
||||
old_suffix, new_suffix, dn)
|
||||
raise ValueError('no replacement made')
|
||||
return DN(*dn[:-len(old_suffix)]) + new_suffix
|
||||
|
||||
@@ -82,15 +76,16 @@ class GenerateUpdateMixin(object):
|
||||
old_definition_container = DN(('cn', 'managed entries'), ('cn', 'plugins'), ('cn', 'config'), suffix)
|
||||
new_definition_container = DN(('cn', 'Definitions'), ('cn', 'Managed Entries'), ('cn', 'etc'), suffix)
|
||||
|
||||
definitions_dn = DN(('cn', 'Definitions'))
|
||||
update_list = []
|
||||
restart = False
|
||||
|
||||
# If the old entries don't exist the server has already been updated.
|
||||
try:
|
||||
definitions_managed_entries, _truncated = ldap.find_entries(
|
||||
definitions_managed_entries, truncated = ldap.find_entries(
|
||||
searchfilter, ['*'], old_definition_container,
|
||||
ldap.SCOPE_ONELEVEL)
|
||||
except errors.NotFound:
|
||||
except errors.NotFound as e:
|
||||
return (False, update_list)
|
||||
|
||||
for entry in definitions_managed_entries:
|
||||
@@ -100,7 +95,7 @@ class GenerateUpdateMixin(object):
|
||||
assert isinstance(old_dn, DN)
|
||||
try:
|
||||
entry = ldap.get_entry(old_dn, ['*'])
|
||||
except errors.NotFound:
|
||||
except errors.NotFound as e:
|
||||
pass
|
||||
else:
|
||||
# Compute the new dn by replacing the old container with the new container
|
||||
@@ -156,8 +151,6 @@ class GenerateUpdateMixin(object):
|
||||
|
||||
return (restart, update_list)
|
||||
|
||||
|
||||
@register()
|
||||
class update_managed_post_first(Updater, GenerateUpdateMixin):
|
||||
"""
|
||||
Update managed entries
|
||||
@@ -165,12 +158,12 @@ class update_managed_post_first(Updater, GenerateUpdateMixin):
|
||||
|
||||
def execute(self, **options):
|
||||
# Never need to restart with the pre-update changes
|
||||
_ignore, update_list = self.generate_update(False)
|
||||
(ignore, update_list) = self.generate_update(False)
|
||||
|
||||
return False, update_list
|
||||
|
||||
api.register(update_managed_post_first)
|
||||
|
||||
@register()
|
||||
class update_managed_post(Updater, GenerateUpdateMixin):
|
||||
"""
|
||||
Update managed entries
|
||||
@@ -180,3 +173,5 @@ class update_managed_post(Updater, GenerateUpdateMixin):
|
||||
(restart, update_list) = self.generate_update(True)
|
||||
|
||||
return restart, update_list
|
||||
|
||||
api.register(update_managed_post)
|
||||
|
||||
@@ -2,24 +2,13 @@
|
||||
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import errors
|
||||
from ipalib import Registry
|
||||
from ipalib import api
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
from ipaserver.install import cainstance
|
||||
from ipaserver.install import certs, cainstance
|
||||
from ipaserver.install import ldapupdate
|
||||
from ipaplatform.paths import paths
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_ca_topology(Updater):
|
||||
"""
|
||||
Updates CA topology configuration entries
|
||||
@@ -27,9 +16,9 @@ class update_ca_topology(Updater):
|
||||
|
||||
def execute(self, **options):
|
||||
|
||||
ca = cainstance.CAInstance(self.api.env.realm)
|
||||
ca = cainstance.CAInstance(self.api.env.realm, certs.NSS_DIR)
|
||||
if not ca.is_configured():
|
||||
logger.debug("CA is not configured on this host")
|
||||
self.log.debug("CA is not configured on this host")
|
||||
return False, []
|
||||
|
||||
ld = ldapupdate.LDAPUpdate(ldapi=True, sub_dict={
|
||||
@@ -39,24 +28,6 @@ class update_ca_topology(Updater):
|
||||
|
||||
ld.update([paths.CA_TOPOLOGY_ULDIF])
|
||||
|
||||
ldap = self.api.Backend.ldap2
|
||||
|
||||
ca_replica_dn = DN(
|
||||
('cn', 'replica'),
|
||||
('cn', 'o=ipaca'),
|
||||
('cn', 'mapping tree'),
|
||||
('cn', 'config'))
|
||||
|
||||
check_interval_attr = 'nsds5replicabinddngroupcheckinterval'
|
||||
default_check_interval = ['60']
|
||||
|
||||
try:
|
||||
ca_replica_entry = ldap.get_entry(ca_replica_dn)
|
||||
except errors.NotFound:
|
||||
pass
|
||||
else:
|
||||
if check_interval_attr not in ca_replica_entry:
|
||||
ca_replica_entry[check_interval_attr] = default_check_interval
|
||||
ldap.update_entry(ca_replica_entry)
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_ca_topology)
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
import logging
|
||||
import time
|
||||
import ldap
|
||||
|
||||
from ipalib.plugable import Registry
|
||||
from ipalib import errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
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:
|
||||
logger.error("Could not find DNA plugin entry: %s",
|
||||
dna_config_base)
|
||||
return False, ()
|
||||
|
||||
try:
|
||||
entry = conn.get_entry(dna_config_base)
|
||||
except errors.NotFound:
|
||||
logger.error("Could not find DNA config entry: %s",
|
||||
dna_config_base)
|
||||
return False, ()
|
||||
|
||||
sharedcfgdn = entry.single_value.get("dnaSharedCfgDN")
|
||||
if sharedcfgdn is not None:
|
||||
sharedcfgdn = DN(sharedcfgdn)
|
||||
else:
|
||||
logger.error(
|
||||
"Could not find DNA shared config DN in entry: %s",
|
||||
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:
|
||||
logger.debug(
|
||||
"Unable to find DNA shared config entry for "
|
||||
"dnaHostname=%s (under %s) so far. Retry in 2 sec.",
|
||||
fqdn, sharedcfgdn
|
||||
)
|
||||
time.sleep(2)
|
||||
else:
|
||||
logger.error(
|
||||
"Could not get dnaHostname entries in %s seconds",
|
||||
max_wait * 2
|
||||
)
|
||||
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:
|
||||
logger.debug(
|
||||
"%d entries dnaHostname=%s under %s. One expected",
|
||||
len(entries), fqdn, sharedcfgdn
|
||||
)
|
||||
|
||||
# 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:
|
||||
logger.error(
|
||||
"Failed to set SASL/GSSAPI bind method/protocol "
|
||||
"in entry %s: %s", entry, e
|
||||
)
|
||||
# no restart, no update
|
||||
return False, ()
|
||||
@@ -1,84 +0,0 @@
|
||||
# Authors:
|
||||
# Florence Blanc-Renaud <flo@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2017 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import Updater
|
||||
from ipalib.install import certstore
|
||||
from ipapython.dn import DN
|
||||
from ipapython.certdb import get_ca_nickname
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_fix_duplicate_cacrt_in_ldap(Updater):
|
||||
"""
|
||||
When multiple entries exist for IPA CA cert in ldap, remove the duplicate
|
||||
|
||||
After this plugin, ds needs to be restarted. This ensures that
|
||||
the attribute uniqueness plugin is working and prevents
|
||||
other plugins from adding duplicates.
|
||||
"""
|
||||
|
||||
def execute(self, **options):
|
||||
# If CA is disabled, no need to check for duplicates of IPA CA
|
||||
ca_enabled = self.api.Command.ca_is_enabled()['result']
|
||||
if not ca_enabled:
|
||||
return True, []
|
||||
|
||||
# Look for the IPA CA cert subject
|
||||
ldap = self.api.Backend.ldap2
|
||||
cacert_subject = certstore.get_ca_subject(
|
||||
ldap,
|
||||
self.api.env.container_ca,
|
||||
self.api.env.basedn)
|
||||
|
||||
# Find if there are other certificates with the same subject
|
||||
# They are duplicates resulting of BZ 1480102
|
||||
base_dn = DN(('cn', 'certificates'), ('cn', 'ipa'), ('cn', 'etc'),
|
||||
self.api.env.basedn)
|
||||
try:
|
||||
filter = ldap.make_filter({'ipaCertSubject': cacert_subject})
|
||||
result, _truncated = ldap.find_entries(
|
||||
base_dn=base_dn,
|
||||
filter=filter,
|
||||
attrs_list=[])
|
||||
except errors.NotFound:
|
||||
# No duplicate, we're good
|
||||
logger.debug("No duplicates for IPA CA in LDAP")
|
||||
return True, []
|
||||
|
||||
logger.debug("Found %d entrie(s) for IPA CA in LDAP", len(result))
|
||||
cacert_dn = DN(('cn', get_ca_nickname(self.api.env.realm)), base_dn)
|
||||
for entry in result:
|
||||
if entry.dn == cacert_dn:
|
||||
continue
|
||||
# Remove the duplicate
|
||||
try:
|
||||
ldap.delete_entry(entry)
|
||||
logger.debug("Removed the duplicate %s", entry.dn)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to remove the duplicate %s: %s",
|
||||
entry.dn, e)
|
||||
|
||||
return True, []
|
||||
@@ -17,18 +17,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
from ipapython.ipa_log_manager import *
|
||||
|
||||
|
||||
@register()
|
||||
class update_idrange_type(Updater):
|
||||
"""
|
||||
Update all ID ranges that do not have ipaRangeType attribute filled.
|
||||
@@ -40,8 +34,8 @@ class update_idrange_type(Updater):
|
||||
|
||||
base_dn = DN(self.api.env.container_ranges, self.api.env.basedn)
|
||||
search_filter = ("(&(objectClass=ipaIDrange)(!(ipaRangeType=*)))")
|
||||
logger.debug("update_idrange_type: search for ID ranges with no "
|
||||
"type set")
|
||||
root_logger.debug("update_idrange_type: search for ID ranges with no "
|
||||
"type set")
|
||||
|
||||
while True:
|
||||
# Run the search in loop to avoid issues when LDAP limits are hit
|
||||
@@ -52,23 +46,24 @@ class update_idrange_type(Updater):
|
||||
['objectclass'], base_dn, time_limit=0, size_limit=0)
|
||||
|
||||
except errors.NotFound:
|
||||
logger.debug("update_idrange_type: no ID range without "
|
||||
"type set found")
|
||||
root_logger.debug("update_idrange_type: no ID range without "
|
||||
"type set found")
|
||||
return False, []
|
||||
|
||||
except errors.ExecutionError as e:
|
||||
logger.error("update_idrange_type: cannot retrieve list "
|
||||
"of ranges with no type set: %s", e)
|
||||
root_logger.error("update_idrange_type: cannot retrieve list "
|
||||
"of ranges with no type set: %s", e)
|
||||
return False, []
|
||||
|
||||
if not entries:
|
||||
# No entry was returned, rather break than continue cycling
|
||||
logger.debug("update_idrange_type: no ID range was returned")
|
||||
root_logger.debug("update_idrange_type: no ID range was "
|
||||
"returned")
|
||||
return False, []
|
||||
|
||||
logger.debug("update_idrange_type: found %d "
|
||||
"idranges to update, truncated: %s",
|
||||
len(entries), truncated)
|
||||
root_logger.debug("update_idrange_type: found %d "
|
||||
"idranges to update, truncated: %s",
|
||||
len(entries), truncated)
|
||||
|
||||
error = False
|
||||
|
||||
@@ -85,36 +80,35 @@ class update_idrange_type(Updater):
|
||||
entry['ipaRangeType'] = ['ipa-local']
|
||||
else:
|
||||
entry['ipaRangeType'] = ['unknown']
|
||||
logger.error("update_idrange_type: could not detect "
|
||||
"range type for entry: %s", str(entry.dn))
|
||||
logger.error("update_idrange_type: ID range type set "
|
||||
"to 'unknown' for entry: %s", str(entry.dn))
|
||||
root_logger.error("update_idrange_type: could not detect "
|
||||
"range type for entry: %s" % str(entry.dn))
|
||||
root_logger.error("update_idrange_type: ID range type set "
|
||||
"to 'unknown' for entry: %s" % str(entry.dn))
|
||||
|
||||
try:
|
||||
ldap.update_entry(entry)
|
||||
except (errors.EmptyModlist, errors.NotFound):
|
||||
pass
|
||||
except errors.ExecutionError as e:
|
||||
logger.debug("update_idrange_type: cannot "
|
||||
"update idrange type: %s", e)
|
||||
root_logger.debug("update_idrange_type: cannot "
|
||||
"update idrange type: %s", e)
|
||||
error = True
|
||||
|
||||
if error:
|
||||
# Exit loop to avoid infinite cycles
|
||||
logger.error("update_idrange_type: error(s) "
|
||||
"detected during idrange type update")
|
||||
root_logger.error("update_idrange_type: error(s) "
|
||||
"detected during idrange type update")
|
||||
return False, []
|
||||
|
||||
elif not truncated:
|
||||
# All affected entries updated, exit the loop
|
||||
logger.debug("update_idrange_type: all affected idranges "
|
||||
"were assigned types")
|
||||
root_logger.debug("update_idrange_type: all affected idranges "
|
||||
"were assigned types")
|
||||
return False, []
|
||||
|
||||
return False, []
|
||||
|
||||
|
||||
@register()
|
||||
class update_idrange_baserid(Updater):
|
||||
"""
|
||||
Update ipa-ad-trust-posix ranges' base RID to 0. This applies to AD trust
|
||||
@@ -128,29 +122,29 @@ class update_idrange_baserid(Updater):
|
||||
search_filter = ("(&(objectClass=ipaTrustedADDomainRange)"
|
||||
"(ipaRangeType=ipa-ad-trust-posix)"
|
||||
"(!(ipaBaseRID=0)))")
|
||||
logger.debug(
|
||||
root_logger.debug(
|
||||
"update_idrange_baserid: search for ipa-ad-trust-posix ID ranges "
|
||||
"with ipaBaseRID != 0"
|
||||
)
|
||||
|
||||
try:
|
||||
(entries, _truncated) = ldap.find_entries(
|
||||
(entries, truncated) = ldap.find_entries(
|
||||
search_filter, ['ipabaserid'], base_dn,
|
||||
paged_search=True, time_limit=0, size_limit=0)
|
||||
|
||||
except errors.NotFound:
|
||||
logger.debug("update_idrange_baserid: no AD domain "
|
||||
"range with posix attributes found")
|
||||
root_logger.debug("update_idrange_baserid: no AD domain "
|
||||
"range with posix attributes found")
|
||||
return False, []
|
||||
|
||||
except errors.ExecutionError as e:
|
||||
logger.error("update_idrange_baserid: cannot retrieve "
|
||||
"list of affected ranges: %s", e)
|
||||
root_logger.error("update_idrange_baserid: cannot retrieve "
|
||||
"list of affected ranges: %s", e)
|
||||
return False, []
|
||||
|
||||
logger.debug("update_idrange_baserid: found %d "
|
||||
"idranges possible to update",
|
||||
len(entries))
|
||||
root_logger.debug("update_idrange_baserid: found %d "
|
||||
"idranges possible to update",
|
||||
len(entries))
|
||||
|
||||
error = False
|
||||
|
||||
@@ -158,22 +152,25 @@ class update_idrange_baserid(Updater):
|
||||
for entry in entries:
|
||||
entry['ipabaserid'] = 0
|
||||
try:
|
||||
logger.debug("Updating existing idrange: %s", entry.dn)
|
||||
root_logger.debug("Updating existing idrange: %s" % (entry.dn))
|
||||
ldap.update_entry(entry)
|
||||
logger.info("Done")
|
||||
root_logger.info("Done")
|
||||
except (errors.EmptyModlist, errors.NotFound):
|
||||
pass
|
||||
except errors.ExecutionError as e:
|
||||
logger.debug("update_idrange_type: cannot "
|
||||
"update idrange: %s", e)
|
||||
root_logger.debug("update_idrange_type: cannot "
|
||||
"update idrange: %s", e)
|
||||
error = True
|
||||
|
||||
if error:
|
||||
logger.error("update_idrange_baserid: error(s) "
|
||||
"detected during idrange baserid update")
|
||||
root_logger.error("update_idrange_baserid: error(s) "
|
||||
"detected during idrange baserid update")
|
||||
else:
|
||||
# All affected entries updated, exit the loop
|
||||
logger.debug("update_idrange_baserid: all affected "
|
||||
"idranges updated")
|
||||
root_logger.debug("update_idrange_baserid: all affected "
|
||||
"idranges updated")
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_idrange_type)
|
||||
api.register(update_idrange_baserid)
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
from ipalib import Registry
|
||||
from ipalib import Updater
|
||||
from ipalib import errors
|
||||
from ipapython.dn import DN
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_ldap_server_list(Updater):
|
||||
"""
|
||||
Update defaultServerList, an option that helps Solaris
|
||||
clients discover LDAP server replicas.
|
||||
"""
|
||||
def execute(self, **options):
|
||||
ldap = self.api.Backend.ldap2
|
||||
|
||||
dn = DN(('cn', 'default'), ('ou', 'profile'), self.api.env.basedn)
|
||||
try:
|
||||
entry = ldap.get_entry(dn)
|
||||
srvlist = entry.single_value.get('defaultServerList', '')
|
||||
srvlist = srvlist.split()
|
||||
if not self.api.env.host in srvlist:
|
||||
srvlist.append(self.api.env.host)
|
||||
attr = ' '.join(srvlist)
|
||||
entry['defaultServerList'] = attr
|
||||
ldap.update_entry(entry)
|
||||
except errors.NotFound:
|
||||
pass
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
pass
|
||||
|
||||
# no restart, no updates
|
||||
return False, ()
|
||||
@@ -83,24 +83,20 @@ No other keys are allowed in the template
|
||||
The plugin also deletes permissions specified in OBSOLETE_PERMISSIONS.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
from ipalib import api, errors
|
||||
from ipapython.dn import DN
|
||||
from ipalib.plugable import Registry
|
||||
from ipalib.plugins import aci
|
||||
from ipalib.plugins.permission import permission, permission_del
|
||||
from ipalib.aci import ACI
|
||||
from ipalib import Updater
|
||||
from ipapython import ipautil
|
||||
from ipaserver.plugins import aci
|
||||
from ipaserver.plugins.permission import permission, permission_del
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
OBSOLETE_PERMISSIONS = {
|
||||
@@ -331,7 +327,7 @@ class update_managed_permissions(Updater):
|
||||
|
||||
for acistr in acistrs:
|
||||
if ACI(acistr).isequal(anonymous_read_aci):
|
||||
logger.debug('Removing anonymous ACI: %s', acistr)
|
||||
self.log.debug('Removing anonymous ACI: %s', acistr)
|
||||
acistrs.remove(acistr)
|
||||
break
|
||||
else:
|
||||
@@ -360,18 +356,18 @@ class update_managed_permissions(Updater):
|
||||
anonymous_read_aci = self.get_anonymous_read_aci(ldap)
|
||||
|
||||
if anonymous_read_aci:
|
||||
logger.debug('Anonymous read ACI: %s', anonymous_read_aci)
|
||||
self.log.debug('Anonymous read ACI: %s', anonymous_read_aci)
|
||||
else:
|
||||
logger.debug('Anonymous ACI not found')
|
||||
self.log.debug('Anonymous ACI not found')
|
||||
|
||||
current_obj = () # initially distinct from any obj value, even None
|
||||
for name, template, obj in self.get_templates():
|
||||
if current_obj != obj:
|
||||
if obj:
|
||||
logger.debug('Updating managed permissions for %s',
|
||||
obj.name)
|
||||
self.log.debug('Updating managed permissions for %s',
|
||||
obj.name)
|
||||
else:
|
||||
logger.debug('Updating non-object managed permissions')
|
||||
self.log.debug('Updating non-object managed permissions')
|
||||
current_obj = obj
|
||||
|
||||
self.update_permission(ldap,
|
||||
@@ -384,15 +380,15 @@ class update_managed_permissions(Updater):
|
||||
self.remove_anonymous_read_aci(ldap, anonymous_read_aci)
|
||||
|
||||
for obsolete_name in OBSOLETE_PERMISSIONS:
|
||||
logger.debug('Deleting obsolete permission %s', obsolete_name)
|
||||
self.log.debug('Deleting obsolete permission %s', obsolete_name)
|
||||
try:
|
||||
self.api.Command[permission_del](unicode(obsolete_name),
|
||||
force=True,
|
||||
version=u'2.101')
|
||||
except errors.NotFound:
|
||||
logger.debug('Obsolete permission not found')
|
||||
self.log.debug('Obsolete permission not found')
|
||||
else:
|
||||
logger.debug('Obsolete permission deleted: %s', obsolete_name)
|
||||
self.log.debug('Obsolete permission deleted: %s', obsolete_name)
|
||||
|
||||
return False, ()
|
||||
|
||||
@@ -433,58 +429,58 @@ class update_managed_permissions(Updater):
|
||||
legacy_entry = ldap.get_entry(legacy_dn,
|
||||
['ipapermissiontype', 'cn'])
|
||||
except errors.NotFound:
|
||||
logger.debug("Legacy permission %s not found", legacy_name)
|
||||
self.log.debug("Legacy permission %s not found", legacy_name)
|
||||
else:
|
||||
if 'ipapermissiontype' not in legacy_entry:
|
||||
if is_new:
|
||||
_acientry, acistr = (
|
||||
acientry, acistr = (
|
||||
permission_plugin._get_aci_entry_and_string(
|
||||
legacy_entry, notfound_ok=True))
|
||||
try:
|
||||
included, excluded = self.get_upgrade_attr_lists(
|
||||
acistr, legacy_acistrs)
|
||||
except IncompatibleACIModification:
|
||||
logger.error(
|
||||
self.log.error(
|
||||
"Permission '%s' has been modified from its "
|
||||
"default; not updating it to '%s'.",
|
||||
legacy_name, name)
|
||||
return
|
||||
else:
|
||||
logger.debug("Merging attributes from legacy "
|
||||
"permission '%s'", legacy_name)
|
||||
logger.debug("Included attrs: %s",
|
||||
', '.join(sorted(included)))
|
||||
logger.debug("Excluded attrs: %s",
|
||||
', '.join(sorted(excluded)))
|
||||
self.log.debug("Merging attributes from legacy "
|
||||
"permission '%s'", legacy_name)
|
||||
self.log.debug("Included attrs: %s",
|
||||
', '.join(sorted(included)))
|
||||
self.log.debug("Excluded attrs: %s",
|
||||
', '.join(sorted(excluded)))
|
||||
entry['ipapermincludedattr'] = list(included)
|
||||
entry['ipapermexcludedattr'] = list(excluded)
|
||||
remove_legacy = True
|
||||
else:
|
||||
logger.debug("Ignoring attributes in legacy "
|
||||
"permission '%s' because '%s' exists",
|
||||
legacy_name, name)
|
||||
self.log.debug("Ignoring attributes in legacy "
|
||||
"permission '%s' because '%s' exists",
|
||||
legacy_name, name)
|
||||
remove_legacy = True
|
||||
else:
|
||||
logger.debug("Ignoring V2 permission named '%s'",
|
||||
legacy_name)
|
||||
self.log.debug("Ignoring V2 permission named '%s'" %
|
||||
legacy_name)
|
||||
|
||||
update_aci = True
|
||||
logger.debug('Updating managed permission: %s', name)
|
||||
self.log.debug('Updating managed permission: %s', name)
|
||||
if is_new:
|
||||
ldap.add_entry(entry)
|
||||
else:
|
||||
try:
|
||||
ldap.update_entry(entry)
|
||||
except errors.EmptyModlist:
|
||||
logger.debug('No changes to permission: %s', name)
|
||||
self.log.debug('No changes to permission: %s', name)
|
||||
update_aci = False
|
||||
|
||||
if update_aci:
|
||||
logger.debug('Updating ACI for managed permission: %s', name)
|
||||
self.log.debug('Updating ACI for managed permission: %s', name)
|
||||
permission_plugin.update_aci(entry)
|
||||
|
||||
if remove_legacy:
|
||||
logger.debug("Removing legacy permission '%s'", legacy_name)
|
||||
self.log.debug("Removing legacy permission '%s'", legacy_name)
|
||||
self.api.Command[permission_del](unicode(legacy_name))
|
||||
|
||||
for name in template.get('replaces_system', ()):
|
||||
@@ -493,14 +489,14 @@ class update_managed_permissions(Updater):
|
||||
entry = ldap.get_entry(permission_plugin.get_dn(name),
|
||||
['ipapermissiontype'])
|
||||
except errors.NotFound:
|
||||
logger.debug("Legacy permission '%s' not found", name)
|
||||
self.log.debug("Legacy permission '%s' not found", name)
|
||||
else:
|
||||
flags = entry.get('ipapermissiontype', [])
|
||||
if list(flags) == ['SYSTEM']:
|
||||
logger.debug("Removing legacy permission '%s'", name)
|
||||
self.log.debug("Removing legacy permission '%s'", name)
|
||||
self.api.Command[permission_del](name, force=True)
|
||||
else:
|
||||
logger.debug("Ignoring V2 permission '%s'", name)
|
||||
self.log.debug("Ignoring V2 permission '%s'", name)
|
||||
|
||||
def get_upgrade_attr_lists(self, current_acistring, default_acistrings):
|
||||
"""Compute included and excluded attributes for a new permission
|
||||
@@ -545,8 +541,8 @@ class update_managed_permissions(Updater):
|
||||
|
||||
current_aci = ACI(current_acistring)
|
||||
current_attrs = _pop_targetattr(current_aci)
|
||||
logger.debug("Current ACI for '%s': %s",
|
||||
current_aci.name, current_acistring)
|
||||
self.log.debug("Current ACI for '%s': %s",
|
||||
current_aci.name, current_acistring)
|
||||
|
||||
attrs_in_all_defaults = None
|
||||
attrs_in_any_defaults = set()
|
||||
@@ -554,11 +550,11 @@ class update_managed_permissions(Updater):
|
||||
for default_acistring in default_acistrings:
|
||||
default_aci = ACI(default_acistring)
|
||||
default_attrs = _pop_targetattr(default_aci)
|
||||
logger.debug("Default ACI for '%s': %s",
|
||||
default_aci.name, default_acistring)
|
||||
self.log.debug("Default ACI for '%s': %s",
|
||||
default_aci.name, default_acistring)
|
||||
|
||||
if current_aci != default_aci:
|
||||
logger.debug('ACIs not compatible')
|
||||
self.log.debug('ACIs not compatible')
|
||||
continue
|
||||
else:
|
||||
all_incompatible = False
|
||||
@@ -570,7 +566,7 @@ class update_managed_permissions(Updater):
|
||||
attrs_in_any_defaults |= default_attrs
|
||||
|
||||
if all_incompatible:
|
||||
logger.debug('All old default ACIs are incompatible')
|
||||
self.log.debug('All old default ACIs are incompatible')
|
||||
raise(IncompatibleACIModification())
|
||||
|
||||
included = current_attrs - attrs_in_any_defaults
|
||||
@@ -663,8 +659,8 @@ class update_managed_permissions(Updater):
|
||||
anonymous_read_aci.target['targetattr']['expression'])
|
||||
read_blacklist &= attributes
|
||||
if read_blacklist:
|
||||
logger.debug('Excluded attributes for %s: %s',
|
||||
name, ', '.join(read_blacklist))
|
||||
self.log.debug('Excluded attributes for %s: %s',
|
||||
name, ', '.join(read_blacklist))
|
||||
entry['ipapermexcludedattr'] = list(read_blacklist)
|
||||
|
||||
# Sanity check
|
||||
@@ -704,7 +700,7 @@ class update_read_replication_agreements_permission(Updater):
|
||||
try:
|
||||
perm_entry = ldap.get_entry(old_perm_dn)
|
||||
except errors.NotFound:
|
||||
logger.debug("Old permission not found")
|
||||
self.log.debug("Old permission not found")
|
||||
return False, ()
|
||||
|
||||
try:
|
||||
@@ -713,9 +709,9 @@ class update_read_replication_agreements_permission(Updater):
|
||||
# we can happily upgrade
|
||||
pass
|
||||
else:
|
||||
logger.error("Permission '%s' cannot be upgraded. "
|
||||
"Permission with target name '%s' already "
|
||||
"exists", old_perm_dn, new_perm_dn)
|
||||
self.log.error("Permission '{}' cannot be upgraded. "
|
||||
"Permission with target name '{}' already "
|
||||
"exists".format(old_perm_dn, new_perm_dn))
|
||||
return False, ()
|
||||
|
||||
# values are case insensitive
|
||||
@@ -733,14 +729,14 @@ class update_read_replication_agreements_permission(Updater):
|
||||
perm_entry['ipapermlocation'] = []
|
||||
perm_entry['ipapermtargetfilter'] = []
|
||||
|
||||
logger.debug("Removing MANAGED attributes from permission %s",
|
||||
old_perm_dn)
|
||||
self.log.debug("Removing MANAGED attributes from permission %s",
|
||||
old_perm_dn)
|
||||
try:
|
||||
ldap.update_entry(perm_entry)
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
|
||||
# do modrdn on permission
|
||||
logger.debug("modrdn: %s -> %s", old_perm_dn, new_perm_dn)
|
||||
self.log.debug("modrdn: %s -> %s", old_perm_dn, new_perm_dn)
|
||||
ldap.move_entry(old_perm_dn, new_perm_dn)
|
||||
return False, ()
|
||||
|
||||
BIN
ipaserver/install/plugins/update_managed_permissions.pyc
Normal file
BIN
ipaserver/install/plugins/update_managed_permissions.pyc
Normal file
Binary file not shown.
@@ -2,10 +2,6 @@
|
||||
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib.plugable import Registry
|
||||
from ipalib import errors
|
||||
from ipalib import Updater
|
||||
@@ -14,8 +10,6 @@ from ipapython.dn import DN
|
||||
from ipaserver.install import sysupgrade
|
||||
from ipaserver.install.ldapupdate import LDAPUpdate
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@@ -38,7 +32,7 @@ class update_nis_configuration(Updater):
|
||||
# maps, we do not want to restore them again
|
||||
return
|
||||
|
||||
logger.debug("Recovering from missing NIS maps bug")
|
||||
self.log.debug("Recovering from missing NIS maps bug")
|
||||
|
||||
suffix = "cn=NIS Server,cn=plugins,cn=config"
|
||||
domain = self.api.env.domain
|
||||
@@ -77,7 +71,7 @@ class update_nis_configuration(Updater):
|
||||
ldap.get_entry(dn, attrs_list=['cn'])
|
||||
except errors.NotFound:
|
||||
# NIS is not configured on system, do not execute update
|
||||
logger.debug("Skipping NIS update, NIS Server is not configured")
|
||||
self.log.debug("Skipping NIS update, NIS Server is not configured")
|
||||
|
||||
# container does not exist, bug #5507 is not effective
|
||||
sysupgrade.set_upgrade_state(
|
||||
@@ -85,7 +79,7 @@ class update_nis_configuration(Updater):
|
||||
else:
|
||||
self.__recover_from_missing_maps(ldap)
|
||||
|
||||
logger.debug("Executing NIS Server update")
|
||||
self.log.debug("Executing NIS Server update")
|
||||
ld = LDAPUpdate(sub_dict={}, ldapi=True)
|
||||
ld.update([paths.NIS_UPDATE_ULDIF])
|
||||
|
||||
|
||||
@@ -17,18 +17,11 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_pacs(Updater):
|
||||
"""
|
||||
Includes default nfs:None only if no nfs: PAC present in ipakrbauthzdata.
|
||||
@@ -42,18 +35,20 @@ class update_pacs(Updater):
|
||||
entry = ldap.get_entry(dn, ['ipakrbauthzdata'])
|
||||
pacs = entry.get('ipakrbauthzdata', [])
|
||||
except errors.NotFound:
|
||||
logger.warning('Error retrieving: %s', str(dn))
|
||||
self.log.warning('Error retrieving: %s' % str(dn))
|
||||
return False, []
|
||||
|
||||
nfs_pac_set = any(pac.startswith('nfs:') for pac in pacs)
|
||||
|
||||
if not nfs_pac_set:
|
||||
logger.debug('Adding nfs:NONE to default PAC types')
|
||||
self.log.debug('Adding nfs:NONE to default PAC types')
|
||||
|
||||
updated_pacs = pacs + [u'nfs:NONE']
|
||||
entry['ipakrbauthzdata'] = updated_pacs
|
||||
ldap.update_entry(entry)
|
||||
else:
|
||||
logger.debug('PAC for nfs is already set, not adding nfs:NONE.')
|
||||
self.log.debug('PAC for nfs is already set, not adding nfs:NONE.')
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_pacs)
|
||||
|
||||
@@ -2,28 +2,21 @@
|
||||
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
from ipapython.ipa_log_manager import root_logger
|
||||
from ipaserver.install import sysupgrade
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_passync_privilege_check(Updater):
|
||||
|
||||
def execute(self, **options):
|
||||
update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
|
||||
if update_done:
|
||||
logger.debug("PassSync privilege update pre-check not needed")
|
||||
root_logger.debug("PassSync privilege update pre-check not needed")
|
||||
return False, []
|
||||
|
||||
logger.debug("Check if there is existing PassSync privilege")
|
||||
root_logger.debug("Check if there is existing PassSync privilege")
|
||||
|
||||
passsync_privilege_dn = DN(('cn','PassSync Service'),
|
||||
self.api.env.container_privilege,
|
||||
@@ -33,16 +26,16 @@ class update_passync_privilege_check(Updater):
|
||||
try:
|
||||
ldap.get_entry(passsync_privilege_dn, [''])
|
||||
except errors.NotFound:
|
||||
logger.debug("PassSync privilege not found, this is a new update")
|
||||
root_logger.debug("PassSync privilege not found, this is a new update")
|
||||
sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', False)
|
||||
else:
|
||||
logger.debug("PassSync privilege found, skip updating PassSync")
|
||||
root_logger.debug("PassSync privilege found, skip updating PassSync")
|
||||
sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', True)
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_passync_privilege_check)
|
||||
|
||||
@register()
|
||||
class update_passync_privilege_update(Updater):
|
||||
"""
|
||||
Add PassSync user as a member of PassSync privilege, if it exists
|
||||
@@ -51,10 +44,10 @@ class update_passync_privilege_update(Updater):
|
||||
def execute(self, **options):
|
||||
update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
|
||||
if update_done:
|
||||
logger.debug("PassSync privilege update not needed")
|
||||
root_logger.debug("PassSync privilege update not needed")
|
||||
return False, []
|
||||
|
||||
logger.debug("Add PassSync user as a member of PassSync privilege")
|
||||
root_logger.debug("Add PassSync user as a member of PassSync privilege")
|
||||
ldap = self.api.Backend.ldap2
|
||||
passsync_dn = DN(('uid','passsync'), ('cn', 'sysaccounts'), ('cn', 'etc'),
|
||||
self.api.env.basedn)
|
||||
@@ -63,13 +56,13 @@ class update_passync_privilege_update(Updater):
|
||||
self.api.env.basedn)
|
||||
|
||||
try:
|
||||
ldap.get_entry(passsync_dn, [''])
|
||||
entry = ldap.get_entry(passsync_dn, [''])
|
||||
except errors.NotFound:
|
||||
logger.debug("PassSync user not found, no update needed")
|
||||
root_logger.debug("PassSync user not found, no update needed")
|
||||
sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', True)
|
||||
return False, []
|
||||
else:
|
||||
logger.debug("PassSync user found, do update")
|
||||
root_logger.debug("PassSync user found, do update")
|
||||
|
||||
update = {'dn': passsync_privilege_dn,
|
||||
'updates': [
|
||||
@@ -79,3 +72,5 @@ class update_passync_privilege_update(Updater):
|
||||
|
||||
sysupgrade.set_upgrade_state('winsync', 'passsync_privilege_updated', True)
|
||||
return False, [update]
|
||||
|
||||
api.register(update_passync_privilege_update)
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from ipalib import Registry
|
||||
from ipalib import Updater
|
||||
from ipalib.install import certmonger
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython.certdb import NSSDatabase
|
||||
from ipaserver.install import cainstance
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_ra_cert_store(Updater):
|
||||
"""
|
||||
Moves the ipaCert store from /etc/httpd/alias RA_AGENT_PEM, RA_AGENT_KEY
|
||||
files
|
||||
"""
|
||||
|
||||
def execute(self, **options):
|
||||
ra_nick = 'ipaCert'
|
||||
ca_enabled = self.api.Command.ca_is_enabled()['result']
|
||||
if not ca_enabled:
|
||||
return False, []
|
||||
|
||||
certdb = NSSDatabase(nssdir=paths.HTTPD_ALIAS_DIR)
|
||||
if not certdb.has_nickname(ra_nick):
|
||||
# Nothign to do
|
||||
return False, []
|
||||
elif os.path.exists(paths.RA_AGENT_PEM):
|
||||
# even though the certificate file exists, we will overwrite it
|
||||
# as it's probabably something wrong anyway
|
||||
logger.warning(
|
||||
"A certificate with the nickname 'ipaCert' exists in "
|
||||
"the old '%s' NSS database as well as in the new "
|
||||
"PEM file '%s'",
|
||||
paths.HTTPD_ALIAS_DIR, paths.RA_AGENT_PEM)
|
||||
|
||||
_fd, p12file = tempfile.mkstemp(dir=certdb.secdir)
|
||||
# no password is necessary as we will be saving it in clear anyway
|
||||
certdb.export_pkcs12(ra_nick, p12file, pkcs12_passwd='')
|
||||
|
||||
# stop tracking the old cert and remove it
|
||||
certmonger.stop_tracking(paths.HTTPD_ALIAS_DIR, nickname=ra_nick)
|
||||
certdb.delete_cert(ra_nick)
|
||||
if os.path.exists(paths.OLD_KRA_AGENT_PEM):
|
||||
os.remove(paths.OLD_KRA_AGENT_PEM)
|
||||
|
||||
# get the private key and certificate from the file and start
|
||||
# tracking it in certmonger
|
||||
ca = cainstance.CAInstance()
|
||||
ca.import_ra_cert(p12file)
|
||||
|
||||
os.remove(p12file)
|
||||
|
||||
return False, []
|
||||
@@ -2,18 +2,11 @@
|
||||
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
from ipapython.ipa_log_manager import root_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_referint(Updater):
|
||||
"""
|
||||
Update referential integrity configuration to new style
|
||||
@@ -33,39 +26,39 @@ class update_referint(Updater):
|
||||
|
||||
def execute(self, **options):
|
||||
|
||||
logger.debug("Upgrading referential integrity plugin configuration")
|
||||
root_logger.debug("Upgrading referential integrity plugin configuration")
|
||||
ldap = self.api.Backend.ldap2
|
||||
try:
|
||||
entry = ldap.get_entry(self.referint_dn)
|
||||
except errors.NotFound:
|
||||
logger.error("Referential integrity configuration not found")
|
||||
root_logger.error("Referential integrity configuration not found")
|
||||
return False, []
|
||||
|
||||
referint_membership_attrs = []
|
||||
|
||||
logger.debug("Initial value: %s", repr(entry))
|
||||
root_logger.debug("Initial value: %s", repr(entry))
|
||||
|
||||
# nsslapd-pluginArg0 -> referint-update-delay
|
||||
update_delay = entry.get('nsslapd-pluginArg0')
|
||||
if update_delay:
|
||||
logger.debug("add: referint-update-delay: %s", update_delay)
|
||||
root_logger.debug("add: referint-update-delay: %s", update_delay)
|
||||
entry['referint-update-delay'] = update_delay
|
||||
entry['nsslapd-pluginArg0'] = None
|
||||
else:
|
||||
logger.debug("Plugin already uses new style, skipping")
|
||||
root_logger.debug("Plugin already uses new style, skipping")
|
||||
return False, []
|
||||
|
||||
# nsslapd-pluginArg1 -> referint-logfile
|
||||
logfile = entry.get('nsslapd-pluginArg1')
|
||||
if logfile:
|
||||
logger.debug("add: referint-logfile: %s", logfile)
|
||||
root_logger.debug("add: referint-logfile: %s", logfile)
|
||||
entry['referint-logfile'] = logfile
|
||||
entry['nsslapd-pluginArg1'] = None
|
||||
|
||||
# nsslapd-pluginArg2 -> referint-logchanges
|
||||
logchanges = entry.get('nsslapd-pluginArg2')
|
||||
if logchanges:
|
||||
logger.debug("add: referint-logchanges: %s", logchanges)
|
||||
root_logger.debug("add: referint-logchanges: %s", logchanges)
|
||||
entry['referint-logchanges'] = logchanges
|
||||
entry['nsslapd-pluginArg2'] = None
|
||||
|
||||
@@ -82,11 +75,13 @@ class update_referint(Updater):
|
||||
# mixing old and new style
|
||||
entry['referint-membership-attr'] = referint_membership_attrs
|
||||
|
||||
logger.debug("Final value: %s", repr(entry))
|
||||
root_logger.debug("Final value: %s", repr(entry))
|
||||
try:
|
||||
ldap.update_entry(entry)
|
||||
except errors.EmptyModlist:
|
||||
logger.debug("No modifications required")
|
||||
root_logger.debug("No modifications required")
|
||||
return False, []
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_referint)
|
||||
|
||||
@@ -17,18 +17,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
from ipapython.ipa_log_manager import *
|
||||
|
||||
|
||||
@register()
|
||||
class update_service_principalalias(Updater):
|
||||
"""
|
||||
Update all services which do not have ipakrbprincipalalias attribute
|
||||
@@ -42,8 +36,8 @@ class update_service_principalalias(Updater):
|
||||
base_dn = DN(self.api.env.container_service, self.api.env.basedn)
|
||||
search_filter = ("(&(objectclass=krbprincipal)(objectclass=ipaservice)"
|
||||
"(!(objectclass=ipakrbprincipal)))")
|
||||
logger.debug("update_service_principalalias: search for affected "
|
||||
"services")
|
||||
root_logger.debug("update_service_principalalias: search for affected "
|
||||
"services")
|
||||
|
||||
while True:
|
||||
# run the search in loop to avoid issues when LDAP limits are hit
|
||||
@@ -53,21 +47,21 @@ class update_service_principalalias(Updater):
|
||||
['objectclass', 'krbprincipalname'], base_dn,
|
||||
time_limit=0, size_limit=0)
|
||||
except errors.NotFound:
|
||||
logger.debug("update_service_principalalias: no service "
|
||||
"to update found")
|
||||
root_logger.debug("update_service_principalalias: no service "
|
||||
"to update found")
|
||||
return False, []
|
||||
except errors.ExecutionError as e:
|
||||
logger.error("update_service_principalalias: cannot "
|
||||
"retrieve list of affected services: %s", e)
|
||||
root_logger.error("update_service_principalalias: cannot "
|
||||
"retrieve list of affected services: %s", e)
|
||||
return False, []
|
||||
if not entries:
|
||||
# no entry was returned, rather break than continue cycling
|
||||
logger.debug("update_service_principalalias: no service "
|
||||
"was returned")
|
||||
root_logger.debug("update_service_principalalias: no service "
|
||||
"was returned")
|
||||
return False, []
|
||||
logger.debug("update_service_principalalias: found %d "
|
||||
"services to update, truncated: %s",
|
||||
len(entries), truncated)
|
||||
root_logger.debug("update_service_principalalias: found %d "
|
||||
"services to update, truncated: %s",
|
||||
len(entries), truncated)
|
||||
|
||||
error = False
|
||||
for entry in entries:
|
||||
@@ -79,18 +73,20 @@ class update_service_principalalias(Updater):
|
||||
except (errors.EmptyModlist, errors.NotFound):
|
||||
pass
|
||||
except errors.ExecutionError as e:
|
||||
logger.debug("update_service_principalalias: cannot "
|
||||
"update service: %s", e)
|
||||
root_logger.debug("update_service_principalalias: cannot "
|
||||
"update service: %s", e)
|
||||
error = True
|
||||
|
||||
if error:
|
||||
# exit loop to avoid infinite cycles
|
||||
logger.error("update_service_principalalias: error(s)"
|
||||
"detected during service update")
|
||||
root_logger.error("update_service_principalalias: error(s)"
|
||||
"detected during service update")
|
||||
return False, []
|
||||
elif not truncated:
|
||||
# all affected entries updated, exit the loop
|
||||
logger.debug("update_service_principalalias: all affected"
|
||||
" services updated")
|
||||
root_logger.debug("update_service_principalalias: all affected"
|
||||
" services updated")
|
||||
return False, []
|
||||
return False, []
|
||||
|
||||
api.register(update_service_principalalias)
|
||||
|
||||
@@ -17,18 +17,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib import Registry, errors
|
||||
from ipalib import api, errors
|
||||
from ipalib import Updater
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
from ipapython.ipa_log_manager import *
|
||||
|
||||
|
||||
@register()
|
||||
class update_uniqueness_plugins_to_new_syntax(Updater):
|
||||
"""
|
||||
Migrate uniqueness plugins to new style syntax
|
||||
@@ -180,13 +174,13 @@ class update_uniqueness_plugins_to_new_syntax(Updater):
|
||||
)
|
||||
|
||||
try:
|
||||
entries, _truncated = ldap.find_entries(
|
||||
entries, truncated = ldap.find_entries(
|
||||
filter=old_style_plugin_search_filter,
|
||||
base_dn=self.plugins_dn,
|
||||
)
|
||||
except errors.NotFound:
|
||||
logger.debug("No uniqueness plugin entries with old style "
|
||||
"configuration found")
|
||||
root_logger.debug("No uniqueness plugin entries with old style "
|
||||
"configuration found")
|
||||
return False, []
|
||||
|
||||
update_list = []
|
||||
@@ -201,14 +195,14 @@ class update_uniqueness_plugins_to_new_syntax(Updater):
|
||||
for entry in entries:
|
||||
# test for mixed configuration
|
||||
if any(attr in entry for attr in new_attributes):
|
||||
logger.critical("Mixed old and new style configuration "
|
||||
"for plugin %s. Plugin will not work. "
|
||||
"Skipping plugin migration, please fix it "
|
||||
"manually",
|
||||
entry.dn)
|
||||
root_logger.critical("Mixed old and new style configuration "
|
||||
"for plugin %s. Plugin will not work. "
|
||||
"Skipping plugin migration, please fix it "
|
||||
"manually",
|
||||
entry.dn)
|
||||
continue
|
||||
logger.debug("Configuration of plugin %s will be migrated "
|
||||
"to new style", entry.dn)
|
||||
root_logger.debug("Configuration of plugin %s will be migrated "
|
||||
"to new style", entry.dn)
|
||||
try:
|
||||
# detect which configuration was used
|
||||
arg0 = entry.get('nsslapd-pluginarg0')
|
||||
@@ -217,10 +211,12 @@ class update_uniqueness_plugins_to_new_syntax(Updater):
|
||||
else:
|
||||
update = self.__subtree_style(entry)
|
||||
except ValueError as e:
|
||||
logger.error("Unable to migrate configuration of "
|
||||
"plugin %s (%s)",
|
||||
entry.dn, e)
|
||||
else:
|
||||
update_list.append(update)
|
||||
root_logger.error("Unable to migrate configuration of "
|
||||
"plugin %s (%s)",
|
||||
entry.dn, e)
|
||||
|
||||
update_list.append(update)
|
||||
|
||||
return False, update_list
|
||||
|
||||
api.register(update_uniqueness_plugins_to_new_syntax)
|
||||
|
||||
@@ -17,40 +17,24 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from ipalib.install import certstore
|
||||
from ipaserver.install import certs, dsinstance
|
||||
from ipaserver.install.installutils import realm_to_serverid
|
||||
from ipalib import Registry, errors
|
||||
from ipaserver.install import certs
|
||||
from ipalib import api, errors, certstore
|
||||
from ipalib import Updater
|
||||
from ipapython import certdb
|
||||
from ipapython.dn import DN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
register = Registry()
|
||||
|
||||
|
||||
@register()
|
||||
class update_upload_cacrt(Updater):
|
||||
"""
|
||||
Upload public CA certificate to LDAP
|
||||
"""
|
||||
|
||||
def execute(self, **options):
|
||||
serverid = realm_to_serverid(self.api.env.realm)
|
||||
db = certs.CertDB(self.api.env.realm,
|
||||
nssdir=dsinstance.config_dirname(serverid))
|
||||
db = certs.CertDB(self.api.env.realm)
|
||||
ca_cert = None
|
||||
|
||||
ca_enabled = self.api.Command.ca_is_enabled()['result']
|
||||
if ca_enabled:
|
||||
ca_nickname = certdb.get_ca_nickname(self.api.env.realm)
|
||||
ca_subject = certstore.get_ca_subject(
|
||||
self.api.Backend.ldap2,
|
||||
self.api.env.container_ca,
|
||||
self.api.env.basedn)
|
||||
else:
|
||||
ca_nickname = None
|
||||
server_certs = db.find_server_certs()
|
||||
@@ -62,20 +46,12 @@ class update_upload_cacrt(Updater):
|
||||
ldap = self.api.Backend.ldap2
|
||||
|
||||
for nickname, trust_flags in db.list_certs():
|
||||
if trust_flags.has_key:
|
||||
if 'u' in trust_flags:
|
||||
continue
|
||||
cert = db.get_cert_from_db(nickname)
|
||||
subject = cert.subject
|
||||
if ca_enabled and subject == ca_subject:
|
||||
# When ca is enabled, we can have the IPA CA cert stored
|
||||
# in the nss db with a different nickname (for instance
|
||||
# when the server was installed with --subject to
|
||||
# customize the CA cert subject), but it must always be
|
||||
# stored in LDAP with the DN cn=$DOMAIN IPA CA
|
||||
# This is why we check the subject instead of the nickname here
|
||||
nickname = ca_nickname
|
||||
trust_flags = certdb.IPA_CA_TRUST_FLAGS
|
||||
trust, _ca, eku = certstore.trust_flags_to_key_policy(trust_flags)
|
||||
if nickname == ca_nickname and ca_enabled:
|
||||
trust_flags = 'CT,C,C'
|
||||
cert = db.get_cert_from_db(nickname, pem=False)
|
||||
trust, ca, eku = certstore.trust_flags_to_key_policy(trust_flags)
|
||||
|
||||
dn = DN(('cn', nickname), ('cn', 'certificates'), ('cn', 'ipa'),
|
||||
('cn','etc'), self.api.env.basedn)
|
||||
@@ -84,8 +60,8 @@ class update_upload_cacrt(Updater):
|
||||
try:
|
||||
certstore.init_ca_entry(entry, cert, nickname, trust, eku)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to create entry for %s: %s",
|
||||
nickname, e)
|
||||
self.log.warning("Failed to create entry for %s: %s",
|
||||
nickname, e)
|
||||
continue
|
||||
if nickname == ca_nickname:
|
||||
ca_cert = cert
|
||||
@@ -97,11 +73,7 @@ class update_upload_cacrt(Updater):
|
||||
try:
|
||||
ldap.add_entry(entry)
|
||||
except errors.DuplicateEntry:
|
||||
if nickname == ca_nickname and ca_enabled:
|
||||
try:
|
||||
ldap.update_entry(entry)
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
pass
|
||||
|
||||
if ca_cert:
|
||||
dn = DN(('cn', 'CACert'), ('cn', 'ipa'), ('cn','etc'),
|
||||
@@ -115,19 +87,10 @@ class update_upload_cacrt(Updater):
|
||||
entry.single_value['cACertificate;binary'] = ca_cert
|
||||
ldap.add_entry(entry)
|
||||
else:
|
||||
force_write = False
|
||||
try:
|
||||
_cert_bin = entry['cACertificate;binary']
|
||||
except ValueError:
|
||||
# BZ 1644874
|
||||
# sometimes the cert is badly stored, twice encoded
|
||||
# force write to fix the value
|
||||
logger.debug('Fixing the value of cACertificate;binary '
|
||||
'in entry %s', entry.dn)
|
||||
force_write = True
|
||||
|
||||
if force_write or b'' in entry['cACertificate;binary']:
|
||||
if b'' in entry['cACertificate;binary']:
|
||||
entry.single_value['cACertificate;binary'] = ca_cert
|
||||
ldap.update_entry(entry)
|
||||
|
||||
return False, []
|
||||
|
||||
api.register(update_upload_cacrt)
|
||||
|
||||
Reference in New Issue
Block a user