ipa/0090-Set-krbCanonicalName-admin-REALM-on-the-admin-user.patch
Florence Blanc-Renaud a96d03c543 ipa-4.12.2-19
- Resolves: RHEL-100450 eDNS: multiple issues during encrypted DNS setup
- Resolves: RHEL-89907 Privilege escalation from host to domain admin in FreeIPA
- Resolves: RHEL-99315 Include latest fixes in python3-ipatests package
- Resolves: RHEL-98565 ipa-idrange-fix: 'Env' object has no attribute 'basedn'
- Resolves: RHEL-96920 Nightly test failure (rawhide) in test_trust.py::TestTrust::test_server_option_with_unreachable_ad
- Resolves: RHEL-31907 kdb: support storing and retrieving multiple master keys

Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
2025-06-30 11:07:39 +02:00

189 lines
6.9 KiB
Diff

From 796ed20092d554ee0c9e23295e346ec1e8a0bf6e Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 28 Apr 2025 13:43:40 -0400
Subject: [PATCH] Set krbCanonicalName=admin@REALM on the admin user
The admin must always own this name. If another entry has this
value set then remove it.
There is a uniqueness plugin for this attribute so the only two
possibilities are:
- no entry has this value set
- the admin user has this value set
- a different entry has the value set
Still, for robustness purposes, the upgrade plugin will handle
more entries.
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
install/share/bootstrap-template.ldif | 1 +
.../updates/90-post_upgrade_plugins.update | 1 +
.../plugins/add_admin_krbcanonicalname.py | 79 +++++++++++++++++++
ipatests/test_integration/test_commands.py | 38 +++++++++
4 files changed, 119 insertions(+)
create mode 100644 ipaserver/install/plugins/add_admin_krbcanonicalname.py
diff --git a/install/share/bootstrap-template.ldif b/install/share/bootstrap-template.ldif
index 325eb8450c786899e7b5e4ae2ef8978f42a8425b..94972eb7270fc9224650bd414c740fc2e8f6c149 100644
--- a/install/share/bootstrap-template.ldif
+++ b/install/share/bootstrap-template.ldif
@@ -239,6 +239,7 @@ objectClass: ipasshuser
uid: admin
krbPrincipalName: admin@$REALM
krbPrincipalName: root@$REALM
+krbCanonicalName: admin@$REALM
cn: Administrator
sn: Administrator
uidNumber: $IDSTART
diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update
index 7c3bba3e0317162d4739513e16b9fac973495c66..3d78c7b5a983f418502a7902a53ff8cd8d6847c4 100644
--- a/install/updates/90-post_upgrade_plugins.update
+++ b/install/updates/90-post_upgrade_plugins.update
@@ -25,6 +25,7 @@ plugin: update_mapping_Guests_to_nobody
plugin: fix_kra_people_entry
plugin: update_pwpolicy
plugin: update_pwpolicy_grace
+plugin: add_admin_krbcanonicalname
# last
# DNS version 1
diff --git a/ipaserver/install/plugins/add_admin_krbcanonicalname.py b/ipaserver/install/plugins/add_admin_krbcanonicalname.py
new file mode 100644
index 0000000000000000000000000000000000000000..e9ffdf55a3f9a1e182bcadda352eda99e536cf16
--- /dev/null
+++ b/ipaserver/install/plugins/add_admin_krbcanonicalname.py
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2025 FreeIPA Contributors see COPYING for license
+#
+
+from __future__ import absolute_import
+
+import logging
+
+from ipalib import errors
+from ipalib import Registry
+from ipalib import Updater
+from ipapython.dn import DN
+
+logger = logging.getLogger(__name__)
+
+register = Registry()
+
+
+@register()
+class add_admin_krbcanonicalname(Updater):
+ """
+ Ensures that only the admin user has the krbCanonicalName of
+ admin@$REALM.
+ """
+
+ def execute(self, **options):
+ ldap = self.api.Backend.ldap2
+
+ search_filter = (
+ "(krbcanonicalname=admin@{})".format(self.api.env.realm))
+ try:
+ (entries, _truncated) = ldap.find_entries(
+ filter=search_filter, base_dn=self.api.env.basedn,
+ time_limit=0, size_limit=0)
+ except errors.EmptyResult:
+ logger.debug("add_admin_krbcanonicalname: No user set with "
+ "admin krbcanonicalname")
+ entries = []
+ # fall through
+ except errors.ExecutionError as e:
+ logger.error("add_admin_krbcanonicalname: Can not get list "
+ "of krbcanonicalname: %s", e)
+ return False, []
+
+ admin_set = False
+ # admin should be only user with admin@ as krbcanonicalname
+ # It has a uniquness setting so there can be only one, we
+ # just didn't automatically set it for admin.
+ for entry in entries:
+ if entry.single_value.get('uid') != 'admin':
+ logger.critical(
+ "add_admin_krbcanonicalname: "
+ "entry %s has a krbcanonicalname of admin. Removing.",
+ entry.dn)
+ del entry['krbcanonicalname']
+ ldap.update_entry(entry)
+ else:
+ admin_set = True
+
+ if not admin_set:
+ dn = DN(
+ ('uid', 'admin'),
+ self.api.env.container_user,
+ self.api.env.basedn)
+ entry = ldap.get_entry(dn)
+ entry['krbcanonicalname'] = 'admin@%s' % self.api.env.realm
+ try:
+ ldap.update_entry(entry)
+ except errors.DuplicateEntry:
+ logger.critical(
+ "add_admin_krbcanonicalname: "
+ "Failed to set krbcanonicalname on admin. It is set "
+ "on another entry.")
+ except errors.ExecutionError as e:
+ logger.critical(
+ "add_admin_krbcanonicalname: "
+ "Failed to set krbcanonicalname on admin: %s", e)
+
+ return False, []
diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py
index 9cad5772127bcd860aeecc8dabe73d5f160faf7b..ad97affe62e15c68442239d669032f0c84e7f5c9 100644
--- a/ipatests/test_integration/test_commands.py
+++ b/ipatests/test_integration/test_commands.py
@@ -2179,6 +2179,44 @@ class TestIPACommandWithoutReplica(IntegrationTest):
assert isrgrootx1_nick in result
+ def test_unique_krbcanonicalname(self):
+ """Verify that the uniqueness for krbcanonicalname is working"""
+ master = self.master
+
+ base_dn = str(master.domain.basedn)
+ hostname = master.hostname
+ realm = master.domain.realm
+ principal = f'test/{hostname}@{realm}'
+ entry_ldif = textwrap.dedent("""
+ dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn}
+ changetype: add
+ ipakrbprincipalalias: test/{hostname}@{realm}
+ krbprincipalname: {principal}
+ objectclass: ipakrbprincipal
+ objectclass: ipaobject
+ objectclass: ipaservice
+ objectclass: krbprincipal
+ objectclass: krbprincipalaux
+ objectclass: top
+ krbcanonicalname: admin@{realm}
+ managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn}
+ """).format(
+ base_dn=base_dn,
+ hostname=hostname,
+ principal=principal,
+ realm=realm)
+ tasks.kdestroy_all(master)
+ master.run_command(
+ ['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}'])
+ args = [
+ 'ldapmodify',
+ '-Y',
+ 'GSSAPI'
+ ]
+ result = master.run_command(args, stdin_text=entry_ldif,
+ raiseonerr=False)
+ assert "entry with the same attribute value" in result.stderr_text
+
class TestIPAautomount(IntegrationTest):
@classmethod
--
2.50.0