summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Babej <tbabej@redhat.com>2015-05-14 10:49:55 +0200
committerJan Cholasta <jcholast@redhat.com>2015-05-26 11:59:47 +0000
commitf3010498af2a4b98512d219b8e09101176c172fe (patch)
treed62ef1b1e718abb0c8565ca84371c2d488686761
parent9eedffdfa62b4fa64244f048969b45b27a995c7a (diff)
downloadfreeipa-f3010498af2a4b98512d219b8e09101176c172fe.tar.gz
freeipa-f3010498af2a4b98512d219b8e09101176c172fe.tar.xz
freeipa-f3010498af2a4b98512d219b8e09101176c172fe.zip
Add Domain Level feature
https://fedorahosted.org/freeipa/ticket/5018 Reviewed-By: Jan Cholasta <jcholast@redhat.com> Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
-rw-r--r--ACI.txt2
-rw-r--r--API.txt9
-rw-r--r--VERSION4
-rw-r--r--install/share/72domainlevels.ldif6
-rw-r--r--install/share/Makefile.am2
-rw-r--r--install/share/domainlevel.ldif7
-rw-r--r--install/share/master-entry.ldif6
-rwxr-xr-xinstall/tools/ipa-replica-install32
-rwxr-xr-xinstall/tools/ipa-server-install22
-rw-r--r--install/updates/72-domainlevels.update14
-rw-r--r--install/updates/Makefile.am1
-rw-r--r--ipalib/constants.py3
-rw-r--r--ipalib/errors.py16
-rw-r--r--ipalib/plugins/domainlevel.py138
-rw-r--r--ipaserver/install/dsinstance.py16
-rw-r--r--ipaserver/install/ldapupdate.py5
-rw-r--r--ipaserver/install/plugins/update_managed_permissions.py11
17 files changed, 280 insertions, 14 deletions
diff --git a/ACI.txt b/ACI.txt
index bf5398929..3c4ebde5b 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -322,6 +322,8 @@ dn: cn=dna,cn=ipa,cn=etc,dc=ipa,dc=example
aci: (targetattr = "cn || createtimestamp || dnahostname || dnaportnum || dnaremainingvalues || dnaremotebindmethod || dnaremoteconnprotocol || dnasecureportnum || entryusn || modifytimestamp || objectclass")(targetfilter = "(objectclass=dnasharedconfig)")(version 3.0;acl "permission:System: Read DNA Configuration";allow (compare,read,search) userdn = "ldap:///all";)
dn: ou=profile,dc=ipa,dc=example
aci: (targetattr = "attributemap || authenticationmethod || bindtimelimit || cn || createtimestamp || credentiallevel || defaultsearchbase || defaultsearchscope || defaultserverlist || dereferencealiases || entryusn || followreferrals || modifytimestamp || objectclass || objectclassmap || ou || preferredserverlist || profilettl || searchtimelimit || serviceauthenticationmethod || servicecredentiallevel || servicesearchdescriptor")(targetfilter = "(|(objectclass=organizationalUnit)(objectclass=DUAConfigProfile))")(version 3.0;acl "permission:System: Read DUA Profile";allow (compare,read,search) userdn = "ldap:///anyone";)
+dn: cn=Domain Level,cn=ipa,cn=etc,dc=ipa,dc=example
+aci: (targetattr = "createtimestamp || entryusn || ipadomainlevel || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipadomainlevelconfig)")(version 3.0;acl "permission:System: Read Domain Level";allow (compare,read,search) userdn = "ldap:///all";)
dn: cn=masters,cn=ipa,cn=etc,dc=ipa,dc=example
aci: (targetattr = "cn || createtimestamp || entryusn || ipaconfigstring || modifytimestamp || objectclass")(targetfilter = "(objectclass=nscontainer)")(version 3.0;acl "permission:System: Read IPA Masters";allow (compare,read,search) groupdn = "ldap:///cn=System: Read IPA Masters,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=config
diff --git a/API.txt b/API.txt
index 38deafefa..66f55e2d1 100644
--- a/API.txt
+++ b/API.txt
@@ -1283,6 +1283,15 @@ option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None)
+command: domainlevel_get
+args: 0,1,1
+option: Str('version?', exclude='webui')
+output: Output('result', <type 'int'>, None)
+command: domainlevel_set
+args: 1,1,1
+arg: Int('ipadomainlevel', cli_name='level', minvalue=0)
+option: Str('version?', exclude='webui')
+output: Output('result', <type 'int'>, None)
command: env
args: 1,3,4
arg: Str('variables*')
diff --git a/VERSION b/VERSION
index 33e7bebe4..071b444a3 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=119
-# Last change: edewata - Added vault plugin
+IPA_API_VERSION_MINOR=120
+# Last change: tbabej - Add Domain Level feature
diff --git a/install/share/72domainlevels.ldif b/install/share/72domainlevels.ldif
new file mode 100644
index 000000000..184e1cb22
--- /dev/null
+++ b/install/share/72domainlevels.ldif
@@ -0,0 +1,6 @@
+dn: cn=schema
+attributeTypes: (2.16.840.1.113730.3.8.19.2.1 NAME 'ipaDomainLevel' DESC 'Domain Level value' EQUALITY numericStringMatch ORDERING numericStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE X-ORIGIN 'IPA v4')
+attributeTypes: (2.16.840.1.113730.3.8.19.2.2 NAME 'ipaMinDomainLevel' DESC 'Minimal supported Domain Level value' EQUALITY numericStringMatch ORDERING numericStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE X-ORIGIN 'IPA v4')
+attributeTypes: (2.16.840.1.113730.3.8.19.2.3 NAME 'ipaMaxDomainLevel' DESC 'Maximal supported Domain Level value' EQUALITY numericStringMatch ORDERING numericStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE X-ORIGIN 'IPA v4')
+objectClasses: (2.16.840.1.113730.3.8.19.1.1 NAME 'ipaDomainLevelConfig' SUP ipaConfigObject AUXILIARY DESC 'Domain Level Configuration' MUST (ipaDomainLevel) X-ORIGIN 'IPA v4')
+objectClasses: (2.16.840.1.113730.3.8.19.1.2 NAME 'ipaSupportedDomainLevelConfig' SUP ipaConfigObject AUXILIARY DESC 'Supported Domain Level Configuration' MUST (ipaMinDomainLevel $ ipaMaxDomainLevel) X-ORIGIN 'IPA v4')
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index c39352caa..8d336690f 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -22,6 +22,7 @@ app_DATA = \
70ipaotp.ldif \
70topology.ldif \
71idviews.ldif \
+ 72domainlevels.ldif \
anonymous-vlv.ldif \
bootstrap-template.ldif \
caJarSigningCert.cfg.template \
@@ -34,6 +35,7 @@ app_DATA = \
ds-nfiles.ldif \
dns.ldif \
dnssec.ldif \
+ domainlevel.ldif \
kerberos.ldif \
indices.ldif \
bind.named.conf.template \
diff --git a/install/share/domainlevel.ldif b/install/share/domainlevel.ldif
new file mode 100644
index 000000000..21ed6a473
--- /dev/null
+++ b/install/share/domainlevel.ldif
@@ -0,0 +1,7 @@
+# Create default Domain Level for new masters
+dn: cn=Domain Level,cn=ipa,cn=etc,$SUFFIX
+changetype: add
+objectClass: top
+objectClass: nsContainer
+objectClass: ipaDomainLevelConfig
+ipaDomainLevel: $DOMAIN_LEVEL
diff --git a/install/share/master-entry.ldif b/install/share/master-entry.ldif
index 34e5b3443..321b8c368 100644
--- a/install/share/master-entry.ldif
+++ b/install/share/master-entry.ldif
@@ -3,5 +3,9 @@ changetype: add
objectclass: top
objectclass: nsContainer
objectclass: ipaReplTopoManagedServer
-ipaReplTopoManagedSuffix: $SUFFIX
+objectClass: ipaConfigObject
+objectClass: ipaSupportedDomainLevelConfig
cn: $FQDN
+ipaReplTopoManagedSuffix: $SUFFIX
+ipaMinDomainLevel: $MIN_DOMAIN_LEVEL
+ipaMaxDomainLevel: $MAX_DOMAIN_LEVEL
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index c75848b1a..1df782b73 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -43,7 +43,7 @@ from ipaserver.install import cainstance
from ipaserver.install import kra
from ipaserver.install import dns as dns_installer
from ipalib import api, create_api, errors, util, certstore, x509
-from ipalib.constants import CACERT
+from ipalib import constants
from ipapython import version
from ipapython.config import IPAOptionParser
from ipapython import sysrestore
@@ -224,12 +224,12 @@ def install_ca_cert(ldap, base_dn, realm, cafile):
try:
certs = certstore.get_ca_certs(ldap, base_dn, realm, False)
except errors.NotFound:
- shutil.copy(cafile, CACERT)
+ shutil.copy(cafile, constants.CACERT)
else:
certs = [c[0] for c in certs if c[2] is not False]
- x509.write_certificate_list(certs, CACERT)
+ x509.write_certificate_list(certs, constants.CACERT)
- os.chmod(CACERT, 0444)
+ os.chmod(constants.CACERT, 0444)
except Exception, e:
print "error copying files: " + str(e)
sys.exit(1)
@@ -569,6 +569,30 @@ def main():
print " %% ipa-replica-manage del %s --force" % config.host_name
exit(3)
+ # Detect the current domain level
+ try:
+ current = remote_api.Command['domainlevel_get']()['result']
+ except errors.NotFound:
+ # If we're joining an older master, domain entry is not
+ # available
+ current = 0
+
+ # Detect if current level is out of supported range
+ # for this IPA version
+ under_lower_bound = current < constants.MIN_DOMAIN_LEVEL
+ above_upper_bound = current > constants.MAX_DOMAIN_LEVEL
+
+ if under_lower_bound or above_upper_bound:
+ message = ("This version of FreeIPA does not support "
+ "the Domain Level which is currently set for "
+ "this domain. The Domain Level needs to be "
+ "raised before installing a replica with "
+ "this version is allowed to be installed "
+ "within this domain.")
+ root_logger.error(message)
+ print(message)
+ exit(3)
+
# Check pre-existing host entry
try:
entry = conn.find_entries(u'fqdn=%s' % config.host_name, ['fqdn'], DN(api.env.container_host, api.env.basedn))
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 9bb8955dc..c7d7c7bff 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -70,7 +70,7 @@ from ipapython import sysrestore
from ipapython.ipautil import *
from ipapython import ipautil
from ipapython import dogtag
-from ipalib import api, errors, util, x509
+from ipalib import api, errors, util, x509, constants
from ipapython.config import IPAOptionParser
from ipalib.util import validate_domain_name
from ipalib.constants import CACERT
@@ -176,6 +176,8 @@ def parse_options():
help="create home directories for users "
"on their first login")
basic_group.add_option("--hostname", dest="host_name", help="fully qualified name of server")
+ basic_group.add_option("--domain-level", dest="domainlevel", help="IPA domain level",
+ default=constants.MAX_DOMAIN_LEVEL, type=int)
basic_group.add_option("--ip-address", dest="ip_addresses",
type="ip", ip_local=True, action="append", default=[],
help="Master Server IP Address. This option can be used multiple times",
@@ -327,6 +329,15 @@ def parse_options():
except ValueError, e:
parser.error("invalid domain: " + unicode(e))
+ # Check that Domain Level is within the allowed range
+ if not options.uninstall:
+ if options.domainlevel < constants.MIN_DOMAIN_LEVEL:
+ parser.error("Domain Level cannot be lower than {0}"
+ .format(constants.MIN_DOMAIN_LEVEL))
+ elif options.domainlevel > constants.MAX_DOMAIN_LEVEL:
+ parser.error("Domain Level cannot be higher than {0}"
+ .format(constants.MAX_DOMAIN_LEVEL))
+
if not options.setup_dns:
if options.forwarders:
parser.error("You cannot specify a --forwarder option without the --setup-dns option")
@@ -1143,21 +1154,24 @@ def main():
ntp.create_instance()
if options.dirsrv_cert_files:
- ds = dsinstance.DsInstance(fstore=fstore)
+ ds = dsinstance.DsInstance(fstore=fstore,
+ domainlevel=options.domainlevel)
ds.create_instance(realm_name, host_name, domain_name,
dm_password, dirsrv_pkcs12_info,
idstart=options.idstart, idmax=options.idmax,
subject_base=options.subject,
hbac_allow=not options.hbac_allow)
else:
- ds = dsinstance.DsInstance(fstore=fstore)
+ ds = dsinstance.DsInstance(fstore=fstore,
+ domainlevel=options.domainlevel)
ds.create_instance(realm_name, host_name, domain_name,
dm_password,
idstart=options.idstart, idmax=options.idmax,
subject_base=options.subject,
hbac_allow=not options.hbac_allow)
else:
- ds = dsinstance.DsInstance(fstore=fstore)
+ ds = dsinstance.DsInstance(fstore=fstore,
+ domainlevel=options.domainlevel)
ds.init_info(
realm_name, host_name, domain_name, dm_password,
options.subject, 1101, 1100, None)
diff --git a/install/updates/72-domainlevels.update b/install/updates/72-domainlevels.update
new file mode 100644
index 000000000..2e83c7be9
--- /dev/null
+++ b/install/updates/72-domainlevels.update
@@ -0,0 +1,14 @@
+# Create default Domain Level entry if it does not exist
+dn: cn=Domain Level,cn=ipa,cn=etc,$SUFFIX
+default: objectClass: top
+default: objectClass: nsContainer
+default: objectClass: ipaDomainLevelConfig
+default: ipaDomainLevel: 0
+
+# Create entry proclaiming Domain Level support of this master
+# This will update the supported Domain Levels during upgrade
+dn: cn=$FQDN,cn=masters,cn=ipa,cn=etc,$SUFFIX
+add: objectClass: ipaConfigObject
+add: objectClass: ipaSupportedDomainLevelConfig
+only: ipaMinDomainLevel: $MIN_DOMAIN_LEVEL
+only: ipaMaxDomainLevel: $MAX_DOMAIN_LEVEL
diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
index 66f6b9d37..4e2da05d6 100644
--- a/install/updates/Makefile.am
+++ b/install/updates/Makefile.am
@@ -49,6 +49,7 @@ app_DATA = \
61-trusts-s4u2proxy.update \
62-ranges.update \
71-idviews.update \
+ 72-domainlevels.update \
90-post_upgrade_plugins.update \
$(NULL)
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 195938a35..b99306eae 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -224,3 +224,6 @@ LDAP_GENERALIZED_TIME_FORMAT = "%Y%m%d%H%M%SZ"
IPA_ANCHOR_PREFIX = ':IPA:'
SID_ANCHOR_PREFIX = ':SID:'
+
+MIN_DOMAIN_LEVEL = 0
+MAX_DOMAIN_LEVEL = 1
diff --git a/ipalib/errors.py b/ipalib/errors.py
index 89b1ef2e0..63ec22269 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -1344,6 +1344,22 @@ class EmptyResult(NotFound):
errno = 4031
+class InvalidDomainLevelError(ExecutionError):
+ """
+ **4032** Raised when a operation could not be completed due to a invalid
+ domain level.
+
+ For example:
+
+ >>> raise InvalidDomainLevelError(reason='feature requires domain level 4')
+ Traceback (most recent call last):
+ ...
+ InvalidDomainLevelError: feature requires domain level 4
+
+ """
+
+ errno = 4032
+
class BuiltinError(ExecutionError):
"""
**4100** Base class for builtin execution errors (*4100 - 4199*).
diff --git a/ipalib/plugins/domainlevel.py b/ipalib/plugins/domainlevel.py
new file mode 100644
index 000000000..64e383006
--- /dev/null
+++ b/ipalib/plugins/domainlevel.py
@@ -0,0 +1,138 @@
+#
+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+#
+
+from collections import namedtuple
+
+from ipalib import _
+from ipalib import Command
+from ipalib import errors
+from ipalib import output
+from ipalib.parameters import Int
+from ipalib.plugable import Registry
+from ipalib.plugins.baseldap import LDAPObject, LDAPUpdate, LDAPRetrieve
+
+from ipapython.dn import DN
+
+
+__doc__ = _("""
+Raise the IPA Domain Level.
+""")
+
+register = Registry()
+
+DomainLevelRange = namedtuple('DomainLevelRange', ['min', 'max'])
+
+domainlevel_output = (
+ output.Output('result', int, _('Current domain level:')),
+)
+
+
+def get_domainlevel_dn(api):
+ domainlevel_dn = DN(
+ ('cn', 'Domain Level'),
+ ('cn', 'ipa'),
+ ('cn', 'etc'),
+ api.env.basedn
+ )
+
+ return domainlevel_dn
+
+
+def get_domainlevel_range(master_entry):
+ try:
+ return DomainLevelRange(
+ int(master_entry['ipaMinDomainLevel'][0]),
+ int(master_entry['ipaMaxDomainLevel'][0])
+ )
+ except KeyError:
+ return DomainLevelRange(0, 0)
+
+
+def get_master_entries(ldap, api):
+ """
+ Returns list of LDAPEntries representing IPA masters.
+ """
+
+ container_masters = DN(
+ ('cn', 'masters'),
+ ('cn', 'ipa'),
+ ('cn', 'etc'),
+ api.env.basedn
+ )
+
+ masters, _ = ldap.find_entries(
+ filter="(cn=*)",
+ base_dn=container_masters,
+ scope=ldap.SCOPE_ONELEVEL,
+ paged_search=True, # we need to make sure to get all of them
+ )
+
+ return masters
+
+
+@register()
+class domainlevel_get(Command):
+ __doc__ = _('Query current Domain Level.')
+
+ has_output = domainlevel_output
+
+ def execute(self, *args, **options):
+ ldap = self.api.Backend.ldap2
+ entry = ldap.get_entry(
+ get_domainlevel_dn(self.api),
+ ['ipaDomainLevel']
+ )
+
+ return {'result': int(entry.single_value['ipaDomainLevel'])}
+
+
+@register()
+class domainlevel_set(Command):
+ __doc__ = _('Change current Domain Level.')
+
+ has_output = domainlevel_output
+
+ takes_args = (
+ Int('ipadomainlevel',
+ cli_name='level',
+ label=_('Domain Level'),
+ minvalue=0,
+ ),
+ )
+
+ def execute(self, *args, **options):
+ """
+ Checks all the IPA masters for supported domain level ranges.
+
+ If the desired domain level is within the supported range of all
+ masters, it will be raised.
+
+ Domain level cannot be lowered.
+ """
+
+ ldap = self.api.Backend.ldap2
+
+ current_entry = ldap.get_entry(get_domainlevel_dn(self.api))
+ current_value = int(current_entry.single_value['ipadomainlevel'])
+ desired_value = int(args[0])
+
+ # Domain level cannot be lowered
+ if int(desired_value) < int(current_value):
+ message = _("Domain Level cannot be lowered.")
+ raise errors.InvalidDomainLevelError(message)
+
+ # Check if every master supports the desired level
+ for master in get_master_entries(ldap, self.api):
+ supported = get_domainlevel_range(master)
+
+ if supported.min > desired_value or supported.max < desired_value:
+ message = _("Domain Level cannot be raised to {0}, server {1} "
+ "does not support it."
+ .format(desired_value, master['cn'][0]))
+ raise errors.InvalidDomainLevelError(message)
+
+ current_entry.single_value['ipaDomainLevel'] = desired_value
+ ldap.update_entry(current_entry)
+
+ return {'result': int(current_entry.single_value['ipaDomainLevel'])}
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 09139405d..064a2ab1d 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -40,6 +40,7 @@ from ipaserver.install import upgradeinstance
from ipalib import api
from ipalib import certstore
from ipalib import errors
+from ipalib import constants
from ipaplatform.tasks import tasks
from ipalib.constants import CACERT
from ipapython.dn import DN
@@ -62,6 +63,7 @@ IPA_SCHEMA_FILES = ("60kerberos.ldif",
"70ipaotp.ldif",
"70topology.ldif",
"71idviews.ldif",
+ "72domainlevels.ldif",
"15rfc2307bis.ldif",
"15rfc4876.ldif")
@@ -186,7 +188,7 @@ info: IPA V2.0
class DsInstance(service.Service):
def __init__(self, realm_name=None, domain_name=None, dm_password=None,
- fstore=None):
+ fstore=None, domainlevel=None):
service.Service.__init__(self, "dirsrv",
service_desc="directory server",
dm_password=dm_password,
@@ -209,6 +211,7 @@ class DsInstance(service.Service):
self.subject_base = None
self.open_ports = []
self.run_init_memberof = True
+ self.domainlevel = domainlevel
if realm_name:
self.suffix = ipautil.realm_to_suffix(self.realm)
self.__setup_sub_dict()
@@ -254,6 +257,7 @@ class DsInstance(service.Service):
def __common_post_setup(self):
self.step("initializing group membership", self.init_memberof)
self.step("adding master entry", self.__add_master_entry)
+ self.step("initializing domain level", self.__set_domain_level)
self.step("configuring Posix uid/gid generation",
self.__config_uidgid_gen)
self.step("adding replication acis", self.__add_replication_acis)
@@ -395,7 +399,10 @@ class DsInstance(service.Service):
IDMAX=self.idmax, HOST=self.fqdn,
ESCAPED_SUFFIX=str(self.suffix),
GROUP=DS_GROUP,
- IDRANGE_SIZE=idrange_size
+ IDRANGE_SIZE=idrange_size,
+ DOMAIN_LEVEL=self.domainlevel,
+ MAX_DOMAIN_LEVEL=constants.MAX_DOMAIN_LEVEL,
+ MIN_DOMAIN_LEVEL=constants.MIN_DOMAIN_LEVEL,
)
def __create_instance(self):
@@ -1011,3 +1018,8 @@ class DsInstance(service.Service):
root_logger.debug('Unable to find certificate subject base in '
'certmap.conf')
return None
+
+ def __set_domain_level(self):
+ # Create global domain level entry and set the domain level
+ if self.domainlevel is not None:
+ self._ldap_mod("domainlevel.ldif", self.sub_dict)
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 5fca37695..f30659fe9 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -39,6 +39,7 @@ from ipaserver.install import installutils
from ipapython import ipautil, ipaldap
from ipalib import errors
from ipalib import api, create_api
+from ipalib import constants
from ipaplatform.paths import paths
from ipaplatform import services
from ipapython.dn import DN
@@ -305,6 +306,10 @@ class LDAPUpdate:
self.sub_dict["TIME"] = int(time.time())
if not self.sub_dict.get("DOMAIN") and domain is not None:
self.sub_dict["DOMAIN"] = domain
+ if not self.sub_dict.get("MIN_DOMAIN_LEVEL"):
+ self.sub_dict["MIN_DOMAIN_LEVEL"] = str(constants.MIN_DOMAIN_LEVEL)
+ if not self.sub_dict.get("MAX_DOMAIN_LEVEL"):
+ self.sub_dict["MAX_DOMAIN_LEVEL"] = str(constants.MAX_DOMAIN_LEVEL)
self.api = create_api(mode=None)
self.api.bootstrap(in_server=True, context='updates')
self.api.finalize()
diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
index 1fbfd9993..11765fba3 100644
--- a/ipaserver/install/plugins/update_managed_permissions.py
+++ b/ipaserver/install/plugins/update_managed_permissions.py
@@ -338,7 +338,16 @@ NONOBJECT_PERMISSIONS = {
'serviceAuthenticationMethod', 'objectclassMap', 'attributeMap',
'profileTTL'
},
- }
+ },
+ 'System: Read Domain Level': {
+ 'ipapermlocation': DN('cn=Domain Level,cn=ipa,cn=etc', api.env.basedn),
+ 'ipapermtargetfilter': {'(objectclass=ipadomainlevelconfig)'},
+ 'ipapermbindruletype': 'all',
+ 'ipapermright': {'read', 'search', 'compare'},
+ 'ipapermdefaultattr': {
+ 'ipadomainlevel', 'objectclass',
+ },
+ },
}