Backports for 4.9.13-9 release:

- Allow the admin user to be disabled
  Resolves: RHEL-34756
- ipa-otptoken-import: open the key file in binary mode
  Resolves: RHEL-39616
- ipa-crlgen-manage: manage the cert status task execution time
  Resolves: RHEL-30280
- idrange-add: add a warning because 389ds restart is required
  Resolves: RHEL-28996
- PKINIT certificate: fix renewal on hidden replica
  Resolves: RHEL-4913, RHEL-45908

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
This commit is contained in:
Rafael Guterres Jeffman 2024-07-17 12:33:21 -03:00
parent a74c5fe996
commit 880d21b828
6 changed files with 667 additions and 1 deletions

View File

@ -0,0 +1,127 @@
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
index 6f5e349..febc22f 100644
--- a/ipaserver/plugins/user.py
+++ b/ipaserver/plugins/user.py
@@ -144,8 +144,7 @@ PROTECTED_USERS = ('admin',)
def check_protected_member(user, protected_group_name=u'admins'):
'''
Ensure admin and the last enabled member of a protected group cannot
- be deleted or disabled by raising ProtectedEntryError or
- LastMemberError as appropriate.
+ be deleted.
'''
if user in PROTECTED_USERS:
@@ -155,6 +154,12 @@ def check_protected_member(user, protected_group_name=u'admins'):
reason=_("privileged user"),
)
+
+def check_last_member(user, protected_group_name=u'admins'):
+ '''
+ Ensure the last enabled member of a protected group cannot
+ be disabled.
+ '''
# Get all users in the protected group
result = api.Command.user_find(in_group=protected_group_name)
@@ -796,6 +801,7 @@ class user_del(baseuser_del):
# If the target entry is a Delete entry, skip the orphaning/removal
# of OTP tokens.
check_protected_member(keys[-1])
+ check_last_member(keys[-1])
preserve = options.get('preserve', False)
@@ -1128,7 +1134,7 @@ class user_disable(LDAPQuery):
def execute(self, *keys, **options):
ldap = self.obj.backend
- check_protected_member(keys[-1])
+ check_last_member(keys[-1])
dn, _oc = self.obj.get_either_dn(*keys, **options)
ldap.deactivate_entry(dn)
diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py
index c0cb4d0..c2a55b8 100644
--- a/ipatests/test_integration/test_commands.py
+++ b/ipatests/test_integration/test_commands.py
@@ -1530,6 +1530,30 @@ class TestIPACommand(IntegrationTest):
assert 'Discovered server %s' % self.master.hostname in result
+ def test_delete_last_enabled_admin(self):
+ """
+ The admin user may be disabled. Don't allow all other
+ members of admins to be removed if the admin user is
+ disabled which would leave the install with no
+ usable admins users
+ """
+ user = 'adminuser2'
+ passwd = 'Secret123'
+ tasks.create_active_user(self.master, user, passwd)
+ tasks.kinit_admin(self.master)
+ self.master.run_command(['ipa', 'group-add-member', 'admins',
+ '--users', user])
+ tasks.kinit_user(self.master, user, passwd)
+ self.master.run_command(['ipa', 'user-disable', 'admin'])
+ result = self.master.run_command(
+ ['ipa', 'user-del', user],
+ raiseonerr=False
+ )
+ self.master.run_command(['ipa', 'user-enable', 'admin'])
+ tasks.kdestroy_all(self.master)
+ assert result.returncode == 1
+ assert 'cannot be deleted or disabled' in result.stderr_text
+
class TestIPACommandWithoutReplica(IntegrationTest):
"""
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index 3c58845..68c6c48 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -1045,8 +1045,8 @@ class TestAdmins(XMLRPC_test):
tracker = Tracker()
command = tracker.make_command('user_disable', admin1)
- with raises_exact(errors.ProtectedEntryError(label=u'user',
- key=admin1, reason='privileged user')):
+ with raises_exact(errors.LastMemberError(label=u'group',
+ key=admin1, container=admin_group)):
command()
def test_create_admin2(self, admin2):
@@ -1064,8 +1064,8 @@ class TestAdmins(XMLRPC_test):
admin2.disable()
tracker = Tracker()
- with raises_exact(errors.ProtectedEntryError(label=u'user',
- key=admin1, reason='privileged user')):
+ with raises_exact(errors.LastMemberError(label=u'group',
+ key=admin1, container=admin_group)):
tracker.run_command('user_disable', admin1)
admin2.delete()
diff --git a/ipatests/test_webui/test_user.py b/ipatests/test_webui/test_user.py
index a8a92d0..9083e50 100644
--- a/ipatests/test_webui/test_user.py
+++ b/ipatests/test_webui/test_user.py
@@ -50,6 +50,8 @@ INV_FIRSTNAME = ("invalid 'first': Leading and trailing spaces are "
FIELD_REQ = 'Required field'
ERR_INCLUDE = 'may only include letters, numbers, _, -, . and $'
ERR_MISMATCH = 'Passwords must match'
+ERR_ADMIN_DISABLE = ('admin cannot be deleted or disabled because '
+ 'it is the last member of group admins')
ERR_ADMIN_DEL = ('user admin cannot be deleted/modified: privileged user')
USR_EXIST = 'user with name "{}" already exists'
ENTRY_EXIST = 'This entry already exists'
@@ -546,7 +548,7 @@ class test_user(user_tasks):
self.select_record('admin')
self.facet_button_click('disable')
self.dialog_button_click('ok')
- self.assert_last_error_dialog(ERR_ADMIN_DEL, details=True)
+ self.assert_last_error_dialog(ERR_ADMIN_DISABLE, details=True)
self.dialog_button_click('ok')
self.assert_record('admin')

View File

@ -0,0 +1,13 @@
diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py
index b3f9347..75e8680 100644
--- a/ipaserver/install/ipa_otptoken_import.py
+++ b/ipaserver/install/ipa_otptoken_import.py
@@ -539,7 +539,7 @@ class OTPTokenImport(admintool.AdminTool):
# Load the keyfile.
keyfile = self.safe_options.keyfile
- with open(keyfile) as f:
+ with open(keyfile, "rb") as f:
self.doc.setKey(f.read())
def run(self):

View File

@ -0,0 +1,114 @@
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 38693c9..35cec89 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -1327,6 +1327,8 @@ class CAInstance(DogtagInstance):
generation master:
- in CS.cfg ca.crl.MasterCRL.enableCRLCache=true
- in CS.cfg ca.crl.MasterCRL.enableCRLUpdates=true
+ - in CS.cfg ca.listenToCloneModifications=true
+ - in CS.cfg ca.certStatusUpdateInterval != 0
- in /etc/httpd/conf.d/ipa-pki-proxy.conf the RewriteRule
^/ipa/crl/MasterCRL.bin is disabled (commented or removed)
@@ -1342,15 +1344,30 @@ class CAInstance(DogtagInstance):
updates = directivesetter.get_directive(
self.config, 'ca.crl.MasterCRL.enableCRLUpdates', '=')
enableCRLUpdates = updates.lower() == 'true'
+ listen = directivesetter.get_directive(
+ self.config, 'ca.listenToCloneModifications', '=')
+ enableToClone = listen.lower() == 'true'
+ updateinterval = directivesetter.get_directive(
+ self.config, 'ca.certStatusUpdateInterval', '=')
# If the values are different, the config is inconsistent
- if enableCRLCache != enableCRLUpdates:
+ if not (enableCRLCache == enableCRLUpdates == enableToClone):
raise InconsistentCRLGenConfigException(
"Configuration is inconsistent, please check "
- "ca.crl.MasterCRL.enableCRLCache and "
- "ca.crl.MasterCRL.enableCRLUpdates in {} and "
+ "ca.crl.MasterCRL.enableCRLCache, "
+ "ca.crl.MasterCRL.enableCRLUpdates and "
+ "ca.listenToCloneModifications in {} and "
"run ipa-crlgen-manage [enable|disable] to repair".format(
self.config))
+ # If they are the same then we are the CRL renewal master. Ensure
+ # the update task is configured.
+ if enableCRLCache and updateinterval == '0':
+ raise InconsistentCRLGenConfigException(
+ "Configuration is inconsistent, please check "
+ "ca.certStatusUpdateInterval in {}. It should "
+ "be either not present or not zero. Run "
+ "ipa-crlgen-manage [enable|disable] to repair".format(
+ self.config))
except IOError:
raise RuntimeError(
"Unable to read {}".format(self.config))
@@ -1407,6 +1424,11 @@ class CAInstance(DogtagInstance):
str_value = str(setup_crlgen).lower()
ds.set('ca.crl.MasterCRL.enableCRLCache', str_value)
ds.set('ca.crl.MasterCRL.enableCRLUpdates', str_value)
+ ds.set('ca.listenToCloneModifications', str_value)
+ if setup_crlgen:
+ ds.set('ca.certStatusUpdateInterval', None)
+ else:
+ ds.set('ca.certStatusUpdateInterval', '0')
# Start pki-tomcat
logger.info("Starting %s", self.service_name)
diff --git a/ipatests/test_integration/test_crlgen_manage.py b/ipatests/test_integration/test_crlgen_manage.py
index 2a733bd..c6f41eb 100644
--- a/ipatests/test_integration/test_crlgen_manage.py
+++ b/ipatests/test_integration/test_crlgen_manage.py
@@ -61,6 +61,16 @@ def check_crlgen_status(host, rc=0, msg=None, enabled=True, check_crl=False):
ext.value.crl_number)
assert number_msg in result.stdout_text
+ try:
+ value = get_CS_cfg_value(host, 'ca.certStatusUpdateInterval')
+ except IOError:
+ return
+
+ if enabled:
+ assert value is None
+ else:
+ assert value == '0'
+
def check_crlgen_enable(host, rc=0, msg=None, check_crl=False):
"""Check ipa-crlgen-manage enable command
@@ -125,6 +135,23 @@ def break_crlgen_with_CS_cfg(host):
check_crlgen_status(host, rc=1, msg="Configuration is inconsistent")
+def get_CS_cfg_value(host, directive):
+ """Retrieve and return the a directive from the CA CS.cfg
+
+ This returns None if the directives is not found.
+ """
+ content = host.get_file_contents(paths.CA_CS_CFG_PATH,
+ encoding='utf-8')
+ value = None
+ for line in content.split('\n'):
+ l = line.lower()
+
+ if l.startswith(directive.lower()):
+ value = line.split('=', 1)[1]
+
+ return value
+
+
class TestCRLGenManage(IntegrationTest):
"""Tests the ipa-crlgen-manage command.
@@ -196,6 +223,9 @@ class TestCRLGenManage(IntegrationTest):
Install a CA clone and enable CRLgen"""
tasks.install_ca(self.replicas[0])
+ value = get_CS_cfg_value(self.replicas[0],
+ 'ca.certStatusUpdateInterval')
+ assert value == '0'
check_crlgen_enable(
self.replicas[0], rc=0,
msg="make sure to have only a single CRL generation master",

View File

@ -0,0 +1,337 @@
diff --git a/ipaserver/plugins/idrange.py b/ipaserver/plugins/idrange.py
index d5b184f..b38ea73 100644
--- a/ipaserver/plugins/idrange.py
+++ b/ipaserver/plugins/idrange.py
@@ -549,6 +549,12 @@ class idrange_add(LDAPCreate):
self.obj.handle_ipabaserid(entry_attrs, options)
self.obj.handle_iparangetype(entry_attrs, options,
keep_objectclass=True)
+ self.add_message(
+ messages.ServiceRestartRequired(
+ service=services.knownservices.dirsrv.service_instance(""),
+ server=_('<all IPA servers>')
+ )
+ )
return dn
diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py
index f912e04..e3f4c23 100644
--- a/ipatests/test_xmlrpc/test_range_plugin.py
+++ b/ipatests/test_xmlrpc/test_range_plugin.py
@@ -372,6 +372,8 @@ IPA_LOCAL_RANGE_MOD_ERR = (
"domain. Run `ipa help idrange` for more information"
)
+dirsrv_instance = services.knownservices.dirsrv.service_instance("")
+
@pytest.mark.tier1
class test_range(Declarative):
@@ -464,6 +466,11 @@ class test_range(Declarative):
),
value=testrange1,
summary=u'Added ID range "%s"' % (testrange1),
+ messages=(
+ messages.ServiceRestartRequired(
+ service=dirsrv_instance,
+ server='<all IPA servers>').to_dict(),
+ ),
),
),
@@ -633,6 +640,11 @@ class test_range(Declarative):
),
value=testrange2,
summary=u'Added ID range "%s"' % (testrange2),
+ messages=(
+ messages.ServiceRestartRequired(
+ service=dirsrv_instance,
+ server='<all IPA servers>').to_dict(),
+ ),
),
),
@@ -792,6 +804,11 @@ class test_range(Declarative):
),
value=unicode(domain7range1),
summary=u'Added ID range "%s"' % (domain7range1),
+ messages=(
+ messages.ServiceRestartRequired(
+ service=dirsrv_instance,
+ server='<all IPA servers>').to_dict(),
+ ),
),
),
@@ -1079,6 +1096,11 @@ class test_range(Declarative):
),
value=testrange9,
summary=u'Added ID range "%s"' % (testrange9),
+ messages=(
+ messages.ServiceRestartRequired(
+ service=dirsrv_instance,
+ server='<all IPA servers>').to_dict(),
+ ),
),
),
diff --git a/ipaserver/plugins/idrange.py b/ipaserver/plugins/idrange.py
index b38ea73..b12e1b8 100644
--- a/ipaserver/plugins/idrange.py
+++ b/ipaserver/plugins/idrange.py
@@ -549,12 +549,15 @@ class idrange_add(LDAPCreate):
self.obj.handle_ipabaserid(entry_attrs, options)
self.obj.handle_iparangetype(entry_attrs, options,
keep_objectclass=True)
- self.add_message(
- messages.ServiceRestartRequired(
- service=services.knownservices.dirsrv.service_instance(""),
- server=_('<all IPA servers>')
+
+ if entry_attrs.single_value.get('iparangetype') in (
+ 'ipa-local', self.obj.range_types.get('ipa-local', None)):
+ self.add_message(
+ messages.ServiceRestartRequired(
+ service=services.knownservices.dirsrv.service_instance(""),
+ server=_('<all IPA servers>')
+ )
)
- )
return dn
@@ -568,7 +571,8 @@ class idrange_del(LDAPDelete):
try:
old_attrs = ldap.get_entry(dn, ['ipabaseid',
'ipaidrangesize',
- 'ipanttrusteddomainsid'])
+ 'ipanttrusteddomainsid',
+ 'iparangetype'])
except errors.NotFound:
raise self.obj.handle_not_found(*keys)
@@ -602,6 +606,20 @@ class idrange_del(LDAPDelete):
key=keys[0],
dependent=trust_domains[0].dn[0].value)
+ self.add_message(
+ messages.ServiceRestartRequired(
+ service=services.knownservices['sssd'].systemd_name,
+ server=_('<all IPA servers>')
+ )
+ )
+
+ if old_attrs.single_value.get('iparangetype') == 'ipa-local':
+ self.add_message(
+ messages.ServiceRestartRequired(
+ service=services.knownservices.dirsrv.service_instance(""),
+ server=_('<all IPA servers>')
+ )
+ )
return dn
@@ -804,10 +822,20 @@ class idrange_mod(LDAPUpdate):
assert isinstance(dn, DN)
self.obj.handle_ipabaserid(entry_attrs, options)
self.obj.handle_iparangetype(entry_attrs, options)
+
+ if entry_attrs.single_value.get('iparangetype') in (
+ 'ipa-local', self.obj.range_types.get('ipa-local', None)):
+ self.add_message(
+ messages.ServiceRestartRequired(
+ service=services.knownservices.dirsrv.service_instance(""),
+ server=_('<all IPA servers>')
+ )
+ )
+
self.add_message(
messages.ServiceRestartRequired(
service=services.knownservices['sssd'].systemd_name,
- server=keys[0]
+ server=_('<all IPA servers>')
)
)
return dn
diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py
index e3f4c23..531fe4a 100644
--- a/ipatests/test_xmlrpc/test_range_plugin.py
+++ b/ipatests/test_xmlrpc/test_range_plugin.py
@@ -26,7 +26,8 @@ import six
from ipalib import api, errors, messages
from ipalib import constants
from ipaplatform import services
-from ipatests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid
+from ipatests.test_xmlrpc.xmlrpc_test import (
+ Declarative, fuzzy_uuid, Fuzzy, fuzzy_sequence_of)
from ipatests.test_xmlrpc import objectclasses
from ipatests.util import MockLDAP
from ipapython.dn import DN
@@ -374,6 +375,8 @@ IPA_LOCAL_RANGE_MOD_ERR = (
dirsrv_instance = services.knownservices.dirsrv.service_instance("")
+fuzzy_restart_messages = fuzzy_sequence_of(Fuzzy(type=dict))
+
@pytest.mark.tier1
class test_range(Declarative):
@@ -610,7 +613,8 @@ class test_range(Declarative):
desc='Delete ID range %r' % testrange1,
command=('idrange_del', [testrange1], {}),
expected=dict(
- result=dict(failed=[]),
+ result=dict(failed=[],
+ messages=fuzzy_restart_messages),
value=[testrange1],
summary=u'Deleted ID range "%s"' % testrange1,
),
@@ -714,7 +718,8 @@ class test_range(Declarative):
desc='Delete ID range %r' % testrange2,
command=('idrange_del', [testrange2], {}),
expected=dict(
- result=dict(failed=[]),
+ result=dict(failed=[],
+ messages=fuzzy_restart_messages),
value=[testrange2],
summary=u'Deleted ID range "%s"' % testrange2,
),
diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py
index 531fe4a..3646952 100644
--- a/ipatests/test_xmlrpc/test_range_plugin.py
+++ b/ipatests/test_xmlrpc/test_range_plugin.py
@@ -613,8 +613,8 @@ class test_range(Declarative):
desc='Delete ID range %r' % testrange1,
command=('idrange_del', [testrange1], {}),
expected=dict(
- result=dict(failed=[],
- messages=fuzzy_restart_messages),
+ result=dict(failed=[]),
+ messages=fuzzy_restart_messages,
value=[testrange1],
summary=u'Deleted ID range "%s"' % testrange1,
),
@@ -718,8 +718,8 @@ class test_range(Declarative):
desc='Delete ID range %r' % testrange2,
command=('idrange_del', [testrange2], {}),
expected=dict(
- result=dict(failed=[],
- messages=fuzzy_restart_messages),
+ result=dict(failed=[]),
+ messages=fuzzy_restart_messages,
value=[testrange2],
summary=u'Deleted ID range "%s"' % testrange2,
),
@@ -809,11 +809,6 @@ class test_range(Declarative):
),
value=unicode(domain7range1),
summary=u'Added ID range "%s"' % (domain7range1),
- messages=(
- messages.ServiceRestartRequired(
- service=dirsrv_instance,
- server='<all IPA servers>').to_dict(),
- ),
),
),
@@ -836,6 +831,7 @@ class test_range(Declarative):
result=dict(failed=[]),
value=[domain1range1],
summary=u'Deleted ID range "%s"' % domain1range1,
+ messages=fuzzy_restart_messages,
),
),
@@ -862,12 +858,7 @@ class test_range(Declarative):
command=('idrange_mod', [domain3range2],
dict(ipabaseid=domain3range1_base_id)),
expected=dict(
- messages=(
- messages.ServiceRestartRequired(
- service=services.knownservices['sssd'].systemd_name,
- server=domain3range2
- ).to_dict(),
- ),
+ messages=fuzzy_restart_messages,
result=dict(
cn=[domain3range2],
ipabaseid=[unicode(domain3range1_base_id)],
@@ -933,12 +924,7 @@ class test_range(Declarative):
command=('idrange_mod', [domain2range1],
dict(ipabaserid=domain5range1_base_rid)),
expected=dict(
- messages=(
- messages.ServiceRestartRequired(
- service=services.knownservices['sssd'].systemd_name,
- server=domain2range1
- ).to_dict(),
- ),
+ messages=fuzzy_restart_messages,
result=dict(
cn=[domain2range1],
ipabaseid=[unicode(domain2range1_base_id)],
@@ -973,12 +959,7 @@ class test_range(Declarative):
command=('idrange_mod', [domain2range1],
dict(ipaautoprivategroups='true')),
expected=dict(
- messages=(
- messages.ServiceRestartRequired(
- service=services.knownservices['sssd'].systemd_name,
- server=domain2range1
- ).to_dict(),
- ),
+ messages=fuzzy_restart_messages,
result=dict(
cn=[domain2range1],
ipabaseid=[unicode(domain2range1_base_id)],
@@ -1000,12 +981,7 @@ class test_range(Declarative):
command=('idrange_mod', [domain2range1],
dict(ipaautoprivategroups='false')),
expected=dict(
- messages=(
- messages.ServiceRestartRequired(
- service=services.knownservices['sssd'].systemd_name,
- server=domain2range1
- ).to_dict(),
- ),
+ messages=fuzzy_restart_messages,
result=dict(
cn=[domain2range1],
ipabaseid=[unicode(domain2range1_base_id)],
@@ -1027,12 +1003,7 @@ class test_range(Declarative):
command=('idrange_mod', [domain2range1],
dict(ipaautoprivategroups='hybrid')),
expected=dict(
- messages=(
- messages.ServiceRestartRequired(
- service=services.knownservices['sssd'].systemd_name,
- server=domain2range1
- ).to_dict(),
- ),
+ messages=fuzzy_restart_messages,
result=dict(
cn=[domain2range1],
ipabaseid=[unicode(domain2range1_base_id)],
@@ -1054,12 +1025,7 @@ class test_range(Declarative):
command=('idrange_mod', [domain2range1],
dict(ipaautoprivategroups='')),
expected=dict(
- messages=(
- messages.ServiceRestartRequired(
- service=services.knownservices['sssd'].systemd_name,
- server=domain2range1
- ).to_dict(),
- ),
+ messages=fuzzy_restart_messages,
result=dict(
cn=[domain2range1],
ipabaseid=[unicode(domain2range1_base_id)],
@@ -1116,6 +1082,7 @@ class test_range(Declarative):
result=dict(failed=[]),
value=[testrange9],
summary=u'Deleted ID range "%s"' % testrange9,
+ messages=fuzzy_restart_messages,
),
),

View File

@ -0,0 +1,58 @@
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index 619be83..9be1b67 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -55,7 +55,7 @@ from ipapython.dn import DN
from ipapython.ipautil import datetime_from_utctimestamp
from ipaserver.plugins.service import normalize_principal, validate_realm
from ipaserver.masters import (
- ENABLED_SERVICE, CONFIGURED_SERVICE, is_service_enabled
+ ENABLED_SERVICE, CONFIGURED_SERVICE, HIDDEN_SERVICE, is_service_enabled
)
try:
@@ -300,7 +300,7 @@ def caacl_check(principal, ca, profile_id):
def ca_kdc_check(api_instance, hostname):
master_dn = api_instance.Object.server.get_dn(unicode(hostname))
kdc_dn = DN(('cn', 'KDC'), master_dn)
- wanted = {ENABLED_SERVICE, CONFIGURED_SERVICE}
+ wanted = {ENABLED_SERVICE, CONFIGURED_SERVICE, HIDDEN_SERVICE}
try:
kdc_entry = api_instance.Backend.ldap2.get_entry(
kdc_dn, ['ipaConfigString'])
diff --git a/ipatests/test_integration/test_replica_promotion.py b/ipatests/test_integration/test_replica_promotion.py
index b71f2d5..7ef44c5 100644
--- a/ipatests/test_integration/test_replica_promotion.py
+++ b/ipatests/test_integration/test_replica_promotion.py
@@ -26,6 +26,7 @@ from ipalib.constants import (
)
from ipaplatform.paths import paths
from ipapython import certdb
+from ipatests.test_integration.test_cert import get_certmonger_fs_id
from ipatests.test_integration.test_dns_locations import (
resolve_records_from_server, IPA_DEFAULT_MASTER_SRV_REC
)
@@ -1241,6 +1242,23 @@ class TestHiddenReplicaPromotion(IntegrationTest):
'ipa-crlgen-manage', 'status'])
assert "CRL generation: enabled" in result.stdout_text
+ def test_hidden_replica_renew_pkinit_cert(self):
+ """Renew the PKINIT cert on a hidden replica.
+
+ Test for https://pagure.io/freeipa/issue/9611
+ """
+ # Get Request ID
+ cmd = ['getcert', 'list', '-f', paths.KDC_CERT]
+ result = self.replicas[0].run_command(cmd)
+ req_id = get_certmonger_fs_id(result.stdout_text)
+
+ self.replicas[0].run_command([
+ 'getcert', 'resubmit', '-f', paths.KDC_CERT
+ ])
+ tasks.wait_for_certmonger_status(
+ self.replicas[0], ('MONITORING'), req_id, timeout=600
+ )
+
class TestHiddenReplicaKRA(IntegrationTest):
"""Test KRA & hidden replica features.

View File

@ -190,7 +190,7 @@
Name: %{package_name}
Version: %{IPA_VERSION}
Release: 11%{?rc_version:.%rc_version}%{?dist}
Release: 12%{?rc_version:.%rc_version}%{?dist}
Summary: The Identity, Policy and Audit system
License: GPLv3+
@ -237,6 +237,11 @@ Patch0025: 0025-dcerpc-invalidate-forest-trust-intfo-cache-when-filtering-o
Patch0026: 0026-backport-test-fixes_rhel#29908.patch
Patch0027: 0027-kdb-fix-vulnerability-in-GCD-rules-handling.patch
Patch0028: 0028-kdb-apply-combinatorial-logic-for-ticket-flags.patch
Patch0029: 0029-Allow_the_admin_user_to_be_disabled_rhel#34756.patch
Patch0030: 0030-ipa-otptoken-import-open-the-key-file-in-binary-mode_rhel#39616.patch
Patch0031: 0031-ipa-crlgen-manage-manage-the-cert-status-task-execution-time_rhel#30280.patch
Patch0032: 0032-idrange-add-add-a-warning-because-389ds-restart-is-required_rhel#28996.patch
Patch0033: 0033-PKINIT-certificate-fix-renewal-on-hidden-replica_rhel#4913.patch
%if 0%{?rhel} >= 8
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
@ -1752,6 +1757,18 @@ fi
%endif
%changelog
* Wed Jul 17 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-9
- Allow the admin user to be disabled
Resolves: RHEL-34756
- ipa-otptoken-import: open the key file in binary mode
Resolves: RHEL-39616
- ipa-crlgen-manage: manage the cert status task execution time
Resolves: RHEL-30280
- idrange-add: add a warning because 389ds restart is required
Resolves: RHEL-28996
- PKINIT certificate: fix renewal on hidden replica
Resolves: RHEL-4913, RHEL-45908
* Wed Jun 12 2024 Julien Rische <jrische@redhat.com> - 4.9.13-11
- Add missing part of backported CVE-2024-3183 fix
Resolves: RHEL-29927