ipa/SOURCES/0040-Set-krbCanonicalName-admin-REALM-on-the-admin-user_rhel#89895.patch
2025-06-23 10:08:09 +00:00

190 lines
6.7 KiB
Diff

From d6d2282f9f1b93ae7fb6e074920e41e64f35ab12 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 325eb8450..94972eb72 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 7c3bba3e0..3d78c7b5a 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 000000000..e9ffdf55a
--- /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 621982c4f..1526a6e0d 100644
--- a/ipatests/test_integration/test_commands.py
+++ b/ipatests/test_integration/test_commands.py
@@ -1796,6 +1796,44 @@ class TestIPACommandWithoutReplica(IntegrationTest):
assert result.returncode == 1
assert 'cannot be deleted or disabled' in result.stderr_text
+ 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 TestIPACommandWithoutReplica(IntegrationTest):
"""
--
2.48.1