ipa-4.12.2-2
- Related: RHEL-59788 Rebase Samba to the latest 4.21.x release - Fixes: RHEL-61642 Uninstall ACME separately during PKI uninstallation - Fixes: RHEL-56963 SSSD offline causing test-adtrust-install failure - Fixes: RHEL-56473 Include latest fixes in python3-ipatests packages - Fixes: RHEL-48104 Default hbac rules are duplicated on remote server post ipa-migrate in prod-mode - Fixes: RHEL-45330 [RFE] add a tool to quickly detect and fix issues with IPA ID ranges - Fixes: RHEL-40376 SID generation task is failing when SELinux is in Enforcing mode - Fixes: RHEL-4915 Last expired OTP token would be c Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
This commit is contained in:
parent
9b3c30c71b
commit
c8a18bb46d
@ -0,0 +1,92 @@
|
||||
From ad4b7f6cedaed54acf279033b650010c65face10 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhir Menon <sumenon@redhat.com>
|
||||
Date: Tue, 20 Aug 2024 14:52:03 +0530
|
||||
Subject: [PATCH] ipatests: Check Default PAC type is added to config
|
||||
|
||||
This patch checks that the default PAC type
|
||||
is added to configuration i.e ipaKrbAuthzData: MS-PAC
|
||||
during ipa-server-installation
|
||||
|
||||
The patch also checks that if 'ipaKrbAuthzData: MS-PAC'
|
||||
attribute is deleted and then when we run 'ipa-server-upgrade'
|
||||
command the attribute is added back.
|
||||
|
||||
Related: https://pagure.io/freeipa/issue/9632
|
||||
|
||||
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
|
||||
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||
---
|
||||
.../test_integration/test_installation.py | 15 +++++++++++
|
||||
ipatests/test_integration/test_upgrade.py | 26 ++++++++++++++++++-
|
||||
2 files changed, 40 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
|
||||
index ada43e33fe173ea3c315178c37e2a664b05b905b..c5565c452010f23f038ddf329454b591ef09f6af 100644
|
||||
--- a/ipatests/test_integration/test_installation.py
|
||||
+++ b/ipatests/test_integration/test_installation.py
|
||||
@@ -1190,6 +1190,21 @@ class TestInstallMaster(IntegrationTest):
|
||||
expected_stdout=f'href="https://{self.master.hostname}/'
|
||||
)
|
||||
|
||||
+ def test_pac_configuration_enabled(self):
|
||||
+ """
|
||||
+ This testcase checks that the default PAC type
|
||||
+ is added to configuration.
|
||||
+ """
|
||||
+ base_dn = str(self.master.domain.basedn)
|
||||
+ dn = DN(
|
||||
+ ("cn", "ipaConfig"),
|
||||
+ ("cn", "etc"),
|
||||
+ base_dn
|
||||
+ )
|
||||
+ result = tasks.ldapsearch_dm(self.master, str(dn),
|
||||
+ ["ipaKrbAuthzData"])
|
||||
+ assert 'ipaKrbAuthzData: MS-PAC' in result.stdout_text
|
||||
+
|
||||
def test_hostname_parameter(self, server_cleanup):
|
||||
"""
|
||||
Test that --hostname parameter is respected in interactive mode.
|
||||
diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py
|
||||
index 011de939e92790734d63da2f85be1c25349116a8..a0f393780ccc25774466992976532c876aa876da 100644
|
||||
--- a/ipatests/test_integration/test_upgrade.py
|
||||
+++ b/ipatests/test_integration/test_upgrade.py
|
||||
@@ -165,7 +165,6 @@ class TestUpgrade(IntegrationTest):
|
||||
ldap.update_entry(location_krb_rec)
|
||||
|
||||
yield _setup_locations
|
||||
-
|
||||
ldap = self.master.ldap_connect()
|
||||
|
||||
modified = False
|
||||
@@ -491,3 +490,28 @@ class TestUpgrade(IntegrationTest):
|
||||
tasks.reinstall_packages(self.master, ['*ipa-client'])
|
||||
assert not self.master.transport.file_exists(
|
||||
paths.SSH_CONFIG + ".orig")
|
||||
+
|
||||
+ def test_mspac_attribute_set(self):
|
||||
+ """
|
||||
+ This testcase deletes the already existing attribute
|
||||
+ 'ipaKrbAuthzData: MS-PAC'.
|
||||
+ The test then runs ipa-server-upgrade and checks that
|
||||
+ the attribute 'ipaKrbAuthzData: MS-PAC' is added again.
|
||||
+ """
|
||||
+ base_dn = str(self.master.domain.basedn)
|
||||
+ dn = DN(
|
||||
+ ("cn", "ipaConfig"),
|
||||
+ ("cn", "etc"),
|
||||
+ base_dn
|
||||
+ )
|
||||
+ ldif = textwrap.dedent("""
|
||||
+ dn: cn=ipaConfig,cn=etc,{}
|
||||
+ changetype: modify
|
||||
+ delete: ipaKrbAuthzData
|
||||
+ """).format(base_dn)
|
||||
+ tasks.ldapmodify_dm(self.master, ldif)
|
||||
+ tasks.kinit_admin(self.master)
|
||||
+ self.master.run_command(['ipa-server-upgrade'])
|
||||
+ result = tasks.ldapsearch_dm(self.master, str(dn),
|
||||
+ ["ipaKrbAuthzData"])
|
||||
+ assert 'ipaKrbAuthzData: MS-PAC' in result.stdout_text
|
||||
--
|
||||
2.46.2
|
||||
|
@ -0,0 +1,86 @@
|
||||
From 42eb97ee6bd8011b590aef321d4386ea9352933d Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
Date: Wed, 28 Aug 2024 10:02:19 +0300
|
||||
Subject: [PATCH] selinux: add all IPA log files to ipa_log_t file context
|
||||
|
||||
We have multiple log files that produced by IPA components. Some of them
|
||||
are written by the tools that run as root and inherit their file context
|
||||
from /var/log -> var_log_t. However, increasingly we get tools that were
|
||||
run through oddjob helpers. These supposed to be run within ipa_helper_t
|
||||
SELinux context which has write permissions for ipa_log_t file context.
|
||||
|
||||
Add all known log files from the base platform. The following script was
|
||||
used to generate them:
|
||||
$ git grep '_LOG = .*ipa.*\.log' ipaplatform/base/paths.py | cut -d= -f2 | \
|
||||
xargs -I% echo -e "%\t--\tgen_context(system_u:object_r:ipa_log_t,s0)"
|
||||
|
||||
/var/log/ipabackup.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaclient-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaclient-uninstall.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaclientsamba-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaclientsamba-uninstall.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipareplica-ca-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipareplica-conncheck.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipareplica-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/iparestore.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaserver-enable-sid.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaserver-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaserver-adtrust-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaserver-dns-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaserver-kra-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaserver-uninstall.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaupgrade.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipatrust-enable-agent.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipaepn.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipa-custodia.audit.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
/var/log/ipa-migrate.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
|
||||
ipa-custodia.audit.log was already in the present list.
|
||||
|
||||
Additionally, ipa-migrate-conflict.ldif is used by the ipa-migrate tool
|
||||
but is not provided through the ipaplatform mechanism. It is added
|
||||
explicitly.
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9654
|
||||
|
||||
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||
---
|
||||
selinux/ipa.fc | 21 ++++++++++++++++++++-
|
||||
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/selinux/ipa.fc b/selinux/ipa.fc
|
||||
index 700e3a14a11fcd403a2e6f57ec781c58dae77660..47bd19ba77418cad1f0904dc4a9a35ce9d6ff9d2 100644
|
||||
--- a/selinux/ipa.fc
|
||||
+++ b/selinux/ipa.fc
|
||||
@@ -24,7 +24,26 @@
|
||||
|
||||
/var/log/ipa(/.*)? gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
|
||||
-/var/log/ipareplica-conncheck.log.* -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipabackup.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaclient-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaclient-uninstall.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaclientsamba-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaclientsamba-uninstall.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipareplica-ca-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipareplica-conncheck.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipareplica-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/iparestore.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaserver-enable-sid.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaserver-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaserver-adtrust-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaserver-dns-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaserver-kra-install.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaserver-uninstall.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaupgrade.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipatrust-enable-agent.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipaepn.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipa-migrate.log -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
+/var/log/ipa-migrate-conflict.ldif -- gen_context(system_u:object_r:ipa_log_t,s0)
|
||||
|
||||
/var/run/ipa(/.*)? gen_context(system_u:object_r:ipa_var_run_t,s0)
|
||||
|
||||
--
|
||||
2.46.2
|
||||
|
1501
0005-Add-ipa-idrange-fix.patch
Normal file
1501
0005-Add-ipa-idrange-fix.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,36 @@
|
||||
From 4fef80aeaaf017b286bd12ebfc30529f6a65a80e Mon Sep 17 00:00:00 2001
|
||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Date: Mon, 2 Sep 2024 18:28:27 +0200
|
||||
Subject: [PATCH] ipatests: Add missing comma in
|
||||
test_idrange_no_rid_bases_reversed
|
||||
|
||||
The test is calling ipa idrange-add but is missing a comma in
|
||||
the arguments list.
|
||||
The resulting call is using "--rid-base 100300000--secondary-rid-base".
|
||||
Add the missing comma to build the command with
|
||||
"--rid-base 100300000 --secondary-rid-base"
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9656
|
||||
|
||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
ipatests/test_integration/test_ipa_idrange_fix.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_ipa_idrange_fix.py b/ipatests/test_integration/test_ipa_idrange_fix.py
|
||||
index de3da9bfd221ce74f1d1bbb0dbe12e4db08b8daa..ff8fbdac9d028d26fc55f5e357f89af879a61723 100644
|
||||
--- a/ipatests/test_integration/test_ipa_idrange_fix.py
|
||||
+++ b/ipatests/test_integration/test_ipa_idrange_fix.py
|
||||
@@ -72,7 +72,7 @@ class TestIpaIdrangeFix(IntegrationTest):
|
||||
"idrange_reversed",
|
||||
"--base-id", '50000',
|
||||
"--range-size", '20000',
|
||||
- "--rid-base", '100300000'
|
||||
+ "--rid-base", '100300000',
|
||||
"--secondary-rid-base", '301000'
|
||||
])
|
||||
|
||||
--
|
||||
2.46.2
|
||||
|
32
0007-ipatests-Update-ipa-adtrust-install-test.patch
Normal file
32
0007-ipatests-Update-ipa-adtrust-install-test.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From a18eb8358675b3697ccf8f8d8dc230cc62df6a4d Mon Sep 17 00:00:00 2001
|
||||
From: Erik Belko <ebelko@redhat.com>
|
||||
Date: Thu, 29 Aug 2024 16:47:21 +0200
|
||||
Subject: [PATCH] ipatests: Update ipa-adtrust-install test
|
||||
|
||||
update test_user_connects_smb_share_if_locked_specific_group with wait
|
||||
for SSSD to be online after ipa-adtrust-install command
|
||||
|
||||
Related: https://pagure.io/freeipa/issue/9655
|
||||
|
||||
Signed-off-by: Erik Belko <ebelko@redhat.com>
|
||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
ipatests/test_integration/test_adtrust_install.py | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_adtrust_install.py b/ipatests/test_integration/test_adtrust_install.py
|
||||
index 72e8d874fb17adadc556ba55b825a88a3ac21a67..de252db1705ad940c3b5ee4df967d7c17a4203a7 100644
|
||||
--- a/ipatests/test_integration/test_adtrust_install.py
|
||||
+++ b/ipatests/test_integration/test_adtrust_install.py
|
||||
@@ -853,6 +853,8 @@ class TestIpaAdTrustInstall(IntegrationTest):
|
||||
self.master.config.admin_password,
|
||||
"-U"]
|
||||
)
|
||||
+ # Wait for SSSD to become online before doing any other check
|
||||
+ tasks.wait_for_sssd_domain_status_online(self.master)
|
||||
self.master.run_command(["mkdir", "/freeipa4234"])
|
||||
self.master.run_command(
|
||||
["chcon", "-t", "samba_share_t",
|
||||
--
|
||||
2.46.2
|
||||
|
33
0008-Installer-activate-ssh-service-in-sssd.conf.patch
Normal file
33
0008-Installer-activate-ssh-service-in-sssd.conf.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 373d41f211c1a04dc432a068bc7d2ba825ff554c Mon Sep 17 00:00:00 2001
|
||||
From: Francisco Trivino <ftrivino@redhat.com>
|
||||
Date: Tue, 13 Aug 2024 12:44:21 +0200
|
||||
Subject: [PATCH] Installer: activate ssh service in sssd.conf
|
||||
|
||||
This commit enables SSSD's ssh service in ipa-client-install to ensure
|
||||
sss_ssh_knownhosts and sss_ssh_knownhostsproxy functions properly.
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9649
|
||||
Related: https://pagure.io/freeipa/issue/9536
|
||||
|
||||
Signed-off-by: Francisco Trivino <ftrivino@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
---
|
||||
ipaclient/install/client.py | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
|
||||
index 802db9614b24553b2b49259f3aebb366093560ac..47a371f629f6ddfb1cd5e9fff9faad737aa01f54 100644
|
||||
--- a/ipaclient/install/client.py
|
||||
+++ b/ipaclient/install/client.py
|
||||
@@ -974,6 +974,8 @@ def configure_sssd_conf(
|
||||
|
||||
sssd_enable_service(sssdconfig, 'nss')
|
||||
sssd_enable_service(sssdconfig, 'pam')
|
||||
+ if options.conf_ssh:
|
||||
+ sssd_enable_service(sssdconfig, 'ssh')
|
||||
|
||||
domain.set_option('ipa_domain', cli_domain)
|
||||
domain.set_option('ipa_hostname', client_hostname)
|
||||
--
|
||||
2.46.2
|
||||
|
413
0009-ipa-migrate-fix-migration-issues-with-entries-using-.patch
Normal file
413
0009-ipa-migrate-fix-migration-issues-with-entries-using-.patch
Normal file
@ -0,0 +1,413 @@
|
||||
From 8d242ba741ec22b258d5e70a530cefd0940783c7 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Reynolds <mreynolds@redhat.com>
|
||||
Date: Tue, 23 Jul 2024 17:07:06 -0400
|
||||
Subject: [PATCH] ipa-migrate - fix migration issues with entries using
|
||||
ipaUniqueId in the RDN
|
||||
|
||||
We need to handle these entries differently and specify what attribute
|
||||
and search base to use to find the entry on the local server. Most
|
||||
entries can use the "cn" attribute but for selinux usermaps we need to
|
||||
search using the ipaOwner attribute which is a DN, and in turn requires
|
||||
additional handling/converting in order to properly check if the usermap
|
||||
exists or not.
|
||||
|
||||
Also fixed an issue where an attribute should be removed from the local
|
||||
entry if it does not exist on the remote entry.
|
||||
|
||||
And fixed the handling od "sudoOrder" which is defined as multi-valued
|
||||
in the schema, but we really need to treat it as single-valued
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9640
|
||||
|
||||
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
---
|
||||
ipaserver/install/ipa_migrate.py | 119 +++++++++++++++++++--
|
||||
ipaserver/install/ipa_migrate_constants.py | 84 +++++++++++++--
|
||||
2 files changed, 188 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/ipaserver/install/ipa_migrate.py b/ipaserver/install/ipa_migrate.py
|
||||
index e21937401b3463335d8297b41a403405071d3795..78c530f24fe5d8c9f5de0f816df9904bf30c7b94 100644
|
||||
--- a/ipaserver/install/ipa_migrate.py
|
||||
+++ b/ipaserver/install/ipa_migrate.py
|
||||
@@ -32,7 +32,7 @@ from ipaserver.install.ipa_migrate_constants import (
|
||||
DS_CONFIG, DB_OBJECTS, DS_INDEXES, BIND_DN, LOG_FILE_NAME,
|
||||
STRIP_OP_ATTRS, STRIP_ATTRS, STRIP_OC, PROD_ATTRS,
|
||||
DNA_REGEN_VAL, DNA_REGEN_ATTRS, NIS_PLUGIN, IGNORE_ATTRS,
|
||||
- DB_EXCLUDE_TREES
|
||||
+ DB_EXCLUDE_TREES, POLICY_OP_ATTRS
|
||||
)
|
||||
|
||||
"""
|
||||
@@ -529,6 +529,14 @@ class IPAMigrate():
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
+ def attr_is_operational(self, attr):
|
||||
+ schema = self.local_conn.schema
|
||||
+ attr_obj = schema.get_obj(ldap.schema.AttributeType, attr)
|
||||
+ if attr_obj is not None:
|
||||
+ if attr_obj.usage == 1:
|
||||
+ return True
|
||||
+ return False
|
||||
+
|
||||
def replace_suffix(self, entry_dn):
|
||||
"""
|
||||
Replace the base DN in an entry DN
|
||||
@@ -1122,6 +1130,18 @@ class IPAMigrate():
|
||||
stats['reset_range'] += 1
|
||||
return entry
|
||||
|
||||
+ def attr_is_required(self, attr, entry):
|
||||
+ """
|
||||
+ Check if an attribute is required in this entry
|
||||
+ """
|
||||
+ entry_oc = entry['objectClass']
|
||||
+ for oc in entry_oc:
|
||||
+ required_attrs = self.local_conn.get_allowed_attributes(
|
||||
+ [oc], raise_on_unknown=False, attributes="must")
|
||||
+ if attr.lower() in required_attrs:
|
||||
+ return True
|
||||
+ return False
|
||||
+
|
||||
def clean_entry(self, entry_dn, entry_type, entry_attrs):
|
||||
"""
|
||||
Clean up the entry from the remote server
|
||||
@@ -1311,7 +1331,17 @@ class IPAMigrate():
|
||||
f"'{old_value}' "
|
||||
"new value "
|
||||
f"'{local_entry[attr][0]}'")
|
||||
-
|
||||
+ elif 'single' == sp_attr[1]:
|
||||
+ # The attribute is defined as multivalued, but
|
||||
+ # we really need to treat it as single valued
|
||||
+ self.log_debug("Entry is different and will "
|
||||
+ f"be updated: '{local_dn}' "
|
||||
+ f"attribute '{attr}' replaced "
|
||||
+ "with val "
|
||||
+ f"'{remote_attrs[attr][0]}' "
|
||||
+ "old value: "
|
||||
+ f"{local_entry[attr][0]}")
|
||||
+ local_entry[attr][0] = remote_attrs[attr][0]
|
||||
goto_next_attr = True
|
||||
break
|
||||
|
||||
@@ -1358,6 +1388,31 @@ class IPAMigrate():
|
||||
local_entry[attr] = remote_attrs[attr]
|
||||
entry_updated = True
|
||||
|
||||
+ # Remove attributes in the local entry that do not exist in the
|
||||
+ # remote entry
|
||||
+ remove_attrs = []
|
||||
+ for attr in local_entry:
|
||||
+ if (self.attr_is_operational(attr)
|
||||
+ and attr.lower() not in POLICY_OP_ATTRS) or \
|
||||
+ attr.lower() in IGNORE_ATTRS or \
|
||||
+ attr.lower() in STRIP_ATTRS or \
|
||||
+ attr.lower() == "usercertificate":
|
||||
+ # This is an attribute that we do not want to remove
|
||||
+ continue
|
||||
+
|
||||
+ if attr not in remote_attrs and \
|
||||
+ not self.attr_is_required(attr, local_entry):
|
||||
+ # Mark this attribute for deletion
|
||||
+ remove_attrs.append(attr)
|
||||
+ entry_updated = True
|
||||
+
|
||||
+ # Remove attributes
|
||||
+ for remove_attr in remove_attrs:
|
||||
+ self.log_debug("Entry is different and will be updated: "
|
||||
+ f"'{local_dn}' attribute '{remove_attr}' "
|
||||
+ "is being removed")
|
||||
+ del local_entry[remove_attr]
|
||||
+
|
||||
if range_reset:
|
||||
stats['reset_range'] += 1
|
||||
|
||||
@@ -1371,6 +1426,9 @@ class IPAMigrate():
|
||||
"""
|
||||
Process chunks of remote entries from a paged results search
|
||||
|
||||
+ entry_dn = the remote entry DN
|
||||
+ entry_attrs = the remote entry's attributes stored in a dict
|
||||
+
|
||||
Identify entry type
|
||||
Process entry (removing/change attr/val/schema)
|
||||
Compare processed remote entry with local entry, merge/overwrite?
|
||||
@@ -1426,6 +1484,47 @@ class IPAMigrate():
|
||||
# Based on the entry type do additional work
|
||||
#
|
||||
|
||||
+ # For entries with alternate identifying needs we need to rebuild the
|
||||
+ # local dn. Typically this is for entries that use ipaUniqueId as the
|
||||
+ # RDN attr
|
||||
+ if entry_type != "custom" and 'alt_id' in DB_OBJECTS[entry_type]:
|
||||
+ attr = DB_OBJECTS[entry_type]['alt_id']['attr']
|
||||
+ base = DB_OBJECTS[entry_type]['alt_id']['base']
|
||||
+ srch_filter = f'{attr}={entry_attrs[attr][0]}'
|
||||
+ if DB_OBJECTS[entry_type]['alt_id']['isDN'] is True:
|
||||
+ # Convert the filter to match the local suffix
|
||||
+ srch_filter = self.replace_suffix(srch_filter)
|
||||
+ srch_base = base + str(self.local_suffix)
|
||||
+
|
||||
+ try:
|
||||
+ entries = self.local_conn.get_entries(DN(srch_base),
|
||||
+ filter=srch_filter)
|
||||
+ if len(entries) == 1:
|
||||
+ local_dn = entries[0].dn
|
||||
+ elif len(entries) == 0:
|
||||
+ # Not found, no problem just proceed and we will add it
|
||||
+ pass
|
||||
+ else:
|
||||
+ # Found too many entries - should not happen
|
||||
+ self.log_error('Found too many local matching entries '
|
||||
+ f'for "{local_dn}"')
|
||||
+ if self.args.force:
|
||||
+ stats['ignored_errors'] += 1
|
||||
+ return
|
||||
+ else:
|
||||
+ sys.exit(1)
|
||||
+ except errors.EmptyResult:
|
||||
+ # Not found, no problem just proceed and we will add it later
|
||||
+ pass
|
||||
+ except (errors.NetworkError, errors.DatabaseError) as e:
|
||||
+ self.log_error('Failed to find a local matching entry for '
|
||||
+ f'"{local_dn}" error: {str(e)}')
|
||||
+ if self.args.force:
|
||||
+ stats['ignored_errors'] += 1
|
||||
+ return
|
||||
+ else:
|
||||
+ sys.exit(1)
|
||||
+
|
||||
# See if the entry exists on the local server
|
||||
try:
|
||||
local_entry = self.local_conn.get_entry(DN(local_dn),
|
||||
@@ -1441,14 +1540,20 @@ class IPAMigrate():
|
||||
|
||||
if self.dryrun:
|
||||
self.write_update_to_ldif(local_entry)
|
||||
- DB_OBJECTS[entry_type]['count'] += 1
|
||||
+ if entry_type == "custom":
|
||||
+ stats['custom'] += 1
|
||||
+ else:
|
||||
+ DB_OBJECTS[entry_type]['count'] += 1
|
||||
stats['total_db_migrated'] += 1
|
||||
return
|
||||
|
||||
# Update the local entry
|
||||
try:
|
||||
self.local_conn.update_entry(local_entry)
|
||||
- DB_OBJECTS[entry_type]['count'] += 1
|
||||
+ if entry_type == "custom":
|
||||
+ stats['custom'] += 1
|
||||
+ else:
|
||||
+ DB_OBJECTS[entry_type]['count'] += 1
|
||||
except errors.ExecutionError as e:
|
||||
self.log_error(f'Failed to update "{local_dn}" error: '
|
||||
f'{str(e)}')
|
||||
@@ -1567,7 +1672,7 @@ class IPAMigrate():
|
||||
"""
|
||||
Used paged search for online method to avoid large memory footprint
|
||||
"""
|
||||
- self.log_info("Migrating database ... (this make take a while)")
|
||||
+ self.log_info("Migrating database ... (this may take a while)")
|
||||
if self.args.db_ldif is not None:
|
||||
self.processDBOffline()
|
||||
else:
|
||||
@@ -1608,7 +1713,7 @@ class IPAMigrate():
|
||||
f"{len(objectclasses)} objectClasses")
|
||||
|
||||
# Loop over attributes and objectclasses and count them
|
||||
- schema = self.local_conn._get_schema()
|
||||
+ schema = self.local_conn.schema
|
||||
local_schema = schema.ldap_entry()
|
||||
for schema_type in [(attributes, "attributeTypes"),
|
||||
(objectclasses, "objectClasses")]:
|
||||
@@ -1967,7 +2072,7 @@ class IPAMigrate():
|
||||
|
||||
# Run ipa-server-upgrade
|
||||
self.log_info("Running ipa-server-upgrade ... "
|
||||
- "(this make take a while)")
|
||||
+ "(this may take a while)")
|
||||
if self.dryrun:
|
||||
self.log_info("Skipping ipa-server-upgrade in dryrun mode.")
|
||||
else:
|
||||
diff --git a/ipaserver/install/ipa_migrate_constants.py b/ipaserver/install/ipa_migrate_constants.py
|
||||
index 0e26c75497b216f09ed450aa25a09c2102582326..250f1b5b01bf066d316a98489ab6153b89615173 100644
|
||||
--- a/ipaserver/install/ipa_migrate_constants.py
|
||||
+++ b/ipaserver/install/ipa_migrate_constants.py
|
||||
@@ -19,6 +19,28 @@ STRIP_OP_ATTRS = [
|
||||
'nsuniqueid',
|
||||
'dsentrydn',
|
||||
'entryuuid',
|
||||
+ 'entrydn',
|
||||
+ 'entryid',
|
||||
+ 'entryusn',
|
||||
+ 'numsubordinates',
|
||||
+ 'parentid',
|
||||
+ 'tombstonenumsubordinates'
|
||||
+]
|
||||
+
|
||||
+# Operational attributes that we would want to remove from the local entry if
|
||||
+# they don't exist in the remote entry
|
||||
+POLICY_OP_ATTRS = [
|
||||
+ 'nsaccountlock',
|
||||
+ 'passwordexpiratontime',
|
||||
+ 'passwordgraceusertime',
|
||||
+ 'pwdpolicysubentry',
|
||||
+ 'passwordexpwarned',
|
||||
+ 'passwordretrycount',
|
||||
+ 'retrycountresettime',
|
||||
+ 'accountunlocktime',
|
||||
+ 'passwordhistory',
|
||||
+ 'passwordallowchangetime',
|
||||
+ 'pwdreset'
|
||||
]
|
||||
|
||||
# Atributes to strip from users/groups
|
||||
@@ -110,7 +132,7 @@ STRIP_OC = [
|
||||
#
|
||||
# The DS_CONFIG mapping breaks each config entry (or type of entry) into its
|
||||
# own catagory. Each catagory, or type, as DN list "dn", the attributes# we
|
||||
-# are intrested in. These attributes are broken into singel valued "attrs",
|
||||
+# are intrested in. These attributes are broken into single valued "attrs",
|
||||
# or multi-valued attributes "multivalued". If the attributes is single
|
||||
# valued then the value is replaced, if it's multivalued then it is "appended"
|
||||
#
|
||||
@@ -503,7 +525,7 @@ DS_CONFIG = {
|
||||
}
|
||||
|
||||
#
|
||||
-# Slpai NIS is an optional plugin. It requires special handling
|
||||
+# Slapi NIS is an optional plugin. It requires special handling
|
||||
#
|
||||
NIS_PLUGIN = {
|
||||
'dn': 'cn=NIS Server,cn=plugins,cn=config',
|
||||
@@ -565,6 +587,12 @@ DS_INDEXES = {
|
||||
# identify the entry.
|
||||
# The "label" and "count" attributes are used for the Summary Report
|
||||
#
|
||||
+# Some entries use ipaUniqueId as the RDN attribute, this makes comparing
|
||||
+# entries between the remote and local servers problematic. So we need special
|
||||
+# identifying information to find the local entry. In this case we use the
|
||||
+# "alt_id" key which is a dict of an attribute 'attr' and partial base DN
|
||||
+# 'base' - which is expected to end in a comma.
|
||||
+#
|
||||
DB_OBJECTS = {
|
||||
# Plugins
|
||||
'automember_def': {
|
||||
@@ -640,8 +668,8 @@ DB_OBJECTS = {
|
||||
'oc': ['ipaconfigobject', 'ipaguiconfig'],
|
||||
'subtree': 'cn=ipaconfig,cn=etc,$SUFFIX',
|
||||
'special_attrs': [
|
||||
- # needs special handling, but
|
||||
- # ipa-server-upgrade rewrites this attribute anyway!
|
||||
+ # needs special handling, but ipa-server-upgrade rewrites this
|
||||
+ # attribute anyway!
|
||||
('ipausersearchfields', 'list'),
|
||||
],
|
||||
'label': 'IPA Config',
|
||||
@@ -772,11 +800,16 @@ DB_OBJECTS = {
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
},
|
||||
- 'subids': { # unknown what these entries look like TODO
|
||||
+ 'subids': {
|
||||
'oc': [],
|
||||
'subtree': ',cn=subids,cn=accounts,$SUFFIX',
|
||||
'label': 'Sub IDs',
|
||||
- 'mode': 'all', # TODO Maybe production only?
|
||||
+ 'mode': 'production',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'ipaOwner',
|
||||
+ 'isDN': True,
|
||||
+ 'base': 'cn=subids,cn=accounts,',
|
||||
+ },
|
||||
'count': 0,
|
||||
},
|
||||
|
||||
@@ -884,6 +917,11 @@ DB_OBJECTS = {
|
||||
'oc': ['ipahbacrule'],
|
||||
'subtree': ',cn=hbac,$SUFFIX',
|
||||
'label': 'HBAC Rules',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'cn',
|
||||
+ 'base': 'cn=hbac,',
|
||||
+ 'isDN': False,
|
||||
+ },
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
},
|
||||
@@ -892,6 +930,11 @@ DB_OBJECTS = {
|
||||
'selinux_usermap': { # Not sure if this is needed, entry is empty TODO
|
||||
'oc': [],
|
||||
'subtree': ',cn=usermap,cn=selinux,$SUFFIX',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'cn',
|
||||
+ 'base': 'cn=usermap,cn=selinux,',
|
||||
+ 'isDN': False,
|
||||
+ },
|
||||
'label': 'Selinux Usermaps',
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
@@ -902,12 +945,27 @@ DB_OBJECTS = {
|
||||
'oc': ['ipasudorule'],
|
||||
'subtree': ',cn=sudorules,cn=sudo,$SUFFIX',
|
||||
'label': 'Sudo Rules',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'cn',
|
||||
+ 'base': 'cn=sudorules,cn=sudo,',
|
||||
+ 'isDN': False,
|
||||
+ },
|
||||
+ 'special_attrs': [
|
||||
+ # schema defines sudoOrder as mutlivalued, but we need to treat
|
||||
+ # it as single valued
|
||||
+ ('sudoorder', 'single'),
|
||||
+ ],
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
},
|
||||
'sudo_cmds': {
|
||||
'oc': ['ipasudocmd'],
|
||||
'subtree': ',cn=sudocmds,cn=sudo,$SUFFIX',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'sudoCmd',
|
||||
+ 'base': 'cn=sudocmds,cn=sudo,',
|
||||
+ 'isDN': False,
|
||||
+ },
|
||||
'label': 'Sudo Commands',
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
@@ -991,6 +1049,11 @@ DB_OBJECTS = {
|
||||
'oc': ['ipanisnetgroup'],
|
||||
'not_oc': ['mepmanagedentry'],
|
||||
'subtree': ',cn=ng,cn=alt,$SUFFIX',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'cn',
|
||||
+ 'base': 'cn=ng,cn=alt,',
|
||||
+ 'isDN': False,
|
||||
+ },
|
||||
'label': 'Network Groups',
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
@@ -1006,9 +1069,14 @@ DB_OBJECTS = {
|
||||
'count': 0,
|
||||
},
|
||||
'caacls': {
|
||||
- 'oc': ['top'],
|
||||
+ 'oc': ['ipacaacl'],
|
||||
'subtree': ',cn=caacls,cn=ca,$SUFFIX',
|
||||
- 'label': 'CA Certificates',
|
||||
+ 'alt_id': {
|
||||
+ 'attr': 'cn',
|
||||
+ 'base': 'cn=caacls,cn=ca,',
|
||||
+ 'isDN': False,
|
||||
+ },
|
||||
+ 'label': 'CA Certificate ACLs',
|
||||
'mode': 'all',
|
||||
'count': 0,
|
||||
},
|
||||
--
|
||||
2.46.2
|
||||
|
68
0010-ipa-migrate-fix-alternate-entry-search-filter.patch
Normal file
68
0010-ipa-migrate-fix-alternate-entry-search-filter.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 3b5a980f5b65b03b9fd7ad0cfbb6c87874d3ff24 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Reynolds <mreynolds@redhat.com>
|
||||
Date: Tue, 3 Sep 2024 13:42:05 -0400
|
||||
Subject: [PATCH] ipa-migrate - fix alternate entry search filter
|
||||
|
||||
Processing a filter like a DN can cause normalization issues that result
|
||||
in an invalid filter. Make sure the filter is encapsulated with
|
||||
parenthesis and we call replace_suffix_value() instead of
|
||||
replace_suffix()
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9658
|
||||
|
||||
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
|
||||
|
||||
Fix typo in test
|
||||
|
||||
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||
---
|
||||
ipaserver/install/ipa_migrate.py | 4 ++--
|
||||
ipatests/test_integration/test_ipa_ipa_migration.py | 6 +++---
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/ipaserver/install/ipa_migrate.py b/ipaserver/install/ipa_migrate.py
|
||||
index 78c530f24fe5d8c9f5de0f816df9904bf30c7b94..38356aa23ea435e2a616f48356feaea7b50dd1e4 100644
|
||||
--- a/ipaserver/install/ipa_migrate.py
|
||||
+++ b/ipaserver/install/ipa_migrate.py
|
||||
@@ -1490,10 +1490,10 @@ class IPAMigrate():
|
||||
if entry_type != "custom" and 'alt_id' in DB_OBJECTS[entry_type]:
|
||||
attr = DB_OBJECTS[entry_type]['alt_id']['attr']
|
||||
base = DB_OBJECTS[entry_type]['alt_id']['base']
|
||||
- srch_filter = f'{attr}={entry_attrs[attr][0]}'
|
||||
+ srch_filter = f'({attr}={entry_attrs[attr][0]})'
|
||||
if DB_OBJECTS[entry_type]['alt_id']['isDN'] is True:
|
||||
# Convert the filter to match the local suffix
|
||||
- srch_filter = self.replace_suffix(srch_filter)
|
||||
+ srch_filter = self.replace_suffix_value(srch_filter)
|
||||
srch_base = base + str(self.local_suffix)
|
||||
|
||||
try:
|
||||
diff --git a/ipatests/test_integration/test_ipa_ipa_migration.py b/ipatests/test_integration/test_ipa_ipa_migration.py
|
||||
index f697bbfbfc6169309274db689501c99fe148cc70..288165e8a83a96e6f6bd4e52866f98617f497c56 100644
|
||||
--- a/ipatests/test_integration/test_ipa_ipa_migration.py
|
||||
+++ b/ipatests/test_integration/test_ipa_ipa_migration.py
|
||||
@@ -610,7 +610,7 @@ class TestIPAMigrateScenario1(IntegrationTest):
|
||||
MIGRATION_SCHEMA_LOG_MSG = "Migrating schema ...\n"
|
||||
MIGRATION_CONFIG_LOG_MSG = "Migrating configuration ...\n"
|
||||
IPA_UPGRADE_LOG_MSG = (
|
||||
- "Running ipa-server-upgrade ... (this make take a while)\n"
|
||||
+ "Running ipa-server-upgrade ... (this may take a while)\n"
|
||||
)
|
||||
SIDGEN_TASK_LOG_MSG = "Running SIDGEN task ...\n"
|
||||
MIGRATION_COMPLETE_LOG_MSG = "Migration complete!\n"
|
||||
@@ -641,10 +641,10 @@ class TestIPAMigrateScenario1(IntegrationTest):
|
||||
tasks.kinit_admin(self.replicas[0])
|
||||
MIGRATION_SCHEMA_LOG_MSG = "Migrating schema ...\n"
|
||||
MIGRATION_DATABASE_LOG_MSG = (
|
||||
- "Migrating database ... (this make take a while)\n"
|
||||
+ "Migrating database ... (this may take a while)\n"
|
||||
)
|
||||
IPA_UPGRADE_LOG_MSG = (
|
||||
- "Running ipa-server-upgrade ... (this make take a while)\n"
|
||||
+ "Running ipa-server-upgrade ... (this may take a while)\n"
|
||||
)
|
||||
SIDGEN_TASK_LOG_MSG = "Running SIDGEN task ...\n"
|
||||
result = run_migrate(
|
||||
--
|
||||
2.46.2
|
||||
|
@ -0,0 +1,67 @@
|
||||
From a343c149838a3058794f33c75c58b75bc1748f7f Mon Sep 17 00:00:00 2001
|
||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Date: Tue, 17 Sep 2024 17:00:49 +0200
|
||||
Subject: [PATCH] ipatests: provide a ccache to rpcclient deletetrustdom
|
||||
|
||||
With samba update to samba-4.20.4, rpcclient now needs a
|
||||
ccache otherwise it prompts for a password.
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9667
|
||||
|
||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
ipatests/pytest_ipa/integration/tasks.py | 23 ++++++++++++++++++++---
|
||||
1 file changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py
|
||||
index 9d6b5f67a311a28c335801d59e0ff0f0c7faccdd..677fb7534256a65940fb5280fa6412789dcba54f 100755
|
||||
--- a/ipatests/pytest_ipa/integration/tasks.py
|
||||
+++ b/ipatests/pytest_ipa/integration/tasks.py
|
||||
@@ -795,15 +795,22 @@ def remove_trust_info_from_ad(master, ad_domain, ad_hostname):
|
||||
kinit_as_user(master,
|
||||
'Administrator@{}'.format(ad_domain.upper()),
|
||||
master.config.ad_admin_password)
|
||||
+ # Find cache for the user
|
||||
+ cache_args = []
|
||||
+ cache = get_credential_cache(master)
|
||||
+ if cache:
|
||||
+ cache_args = ["--use-krb5-ccache", cache]
|
||||
+
|
||||
# Detect whether rpcclient supports -k or --use-kerberos option
|
||||
res = master.run_command(['rpcclient', '-h'], raiseonerr=False)
|
||||
if "--use-kerberos" in res.stderr_text:
|
||||
rpcclient_krb5_knob = "--use-kerberos=desired"
|
||||
else:
|
||||
rpcclient_krb5_knob = "-k"
|
||||
- master.run_command(['rpcclient', rpcclient_krb5_knob, ad_hostname,
|
||||
- '-c', 'deletetrustdom {}'.format(master.domain.name)],
|
||||
- raiseonerr=False)
|
||||
+ cmd_args = ['rpcclient', rpcclient_krb5_knob, ad_hostname]
|
||||
+ cmd_args.extend(cache_args)
|
||||
+ cmd_args.extend(['-c', 'deletetrustdom {}'.format(master.domain.name)])
|
||||
+ master.run_command(cmd_args, raiseonerr=False)
|
||||
|
||||
|
||||
def configure_auth_to_local_rule(master, ad):
|
||||
@@ -1086,6 +1093,16 @@ def kinit_admin(host, raiseonerr=True):
|
||||
raiseonerr=raiseonerr)
|
||||
|
||||
|
||||
+def get_credential_cache(host):
|
||||
+ # Return the credential cache currently in use on host or None
|
||||
+ result = host.run_command(["klist"]).stdout_text
|
||||
+ pattern = re.compile(r'Ticket cache: (?P<cache>.*)\n')
|
||||
+ res = pattern.search(result)
|
||||
+ if res:
|
||||
+ return res['cache']
|
||||
+ return None
|
||||
+
|
||||
+
|
||||
def uninstall_master(host, ignore_topology_disconnect=True,
|
||||
ignore_last_of_role=True, clean=True, verbose=False):
|
||||
uninstall_cmd = ['ipa-server-install', '--uninstall', '-U']
|
||||
--
|
||||
2.46.2
|
||||
|
@ -0,0 +1,60 @@
|
||||
From 743c7b46e463bef666dc84e9f513eb7dee7f59f6 Mon Sep 17 00:00:00 2001
|
||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Date: Tue, 17 Sep 2024 14:48:58 +0200
|
||||
Subject: [PATCH] test_adtrust_install: add --use-krb5-ccache to smbclient
|
||||
command
|
||||
|
||||
With samba 4.20.4 the smbclient commands needs a ccache otherwise it
|
||||
prompts for a password.
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9666
|
||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
.../test_integration/test_adtrust_install.py | 28 ++++++++++++-------
|
||||
1 file changed, 18 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_adtrust_install.py b/ipatests/test_integration/test_adtrust_install.py
|
||||
index de252db1705ad940c3b5ee4df967d7c17a4203a7..79a91dfaa61276de74b10777c6d44b5942ed1be0 100644
|
||||
--- a/ipatests/test_integration/test_adtrust_install.py
|
||||
+++ b/ipatests/test_integration/test_adtrust_install.py
|
||||
@@ -873,17 +873,25 @@ class TestIpaAdTrustInstall(IntegrationTest):
|
||||
"path", "/freeipa4234"])
|
||||
self.master.run_command(["touch", "before"])
|
||||
self.master.run_command(["touch", "after"])
|
||||
- self.master.run_command(
|
||||
- ["smbclient", "--use-kerberos=desired",
|
||||
- "-c=put before", "//{}/share".format(
|
||||
- self.master.hostname)]
|
||||
- )
|
||||
+ # Find cache for the admin user
|
||||
+ cache_args = []
|
||||
+ cache = tasks.get_credential_cache(self.master)
|
||||
+ if cache:
|
||||
+ cache_args = ["--use-krb5-ccache", cache]
|
||||
+
|
||||
+ cmd_args = ["smbclient", "--use-kerberos=desired"]
|
||||
+ cmd_args.extend(cache_args)
|
||||
+ cmd_args.extend([
|
||||
+ "-c=put before", "//{}/share".format(self.master.hostname)
|
||||
+ ])
|
||||
+ self.master.run_command(cmd_args)
|
||||
self.master.run_command(
|
||||
["net", "conf", "setparm", "share",
|
||||
"valid users", "@admins"])
|
||||
- result = self.master.run_command(
|
||||
- ["smbclient", "--use-kerberos=desired",
|
||||
- "-c=put after", "//{}/share".format(
|
||||
- self.master.hostname)]
|
||||
- )
|
||||
+ cmd_args = ["smbclient", "--use-kerberos=desired"]
|
||||
+ cmd_args.extend(cache_args)
|
||||
+ cmd_args.extend([
|
||||
+ "-c=put after", "//{}/share".format(self.master.hostname)
|
||||
+ ])
|
||||
+ result = self.master.run_command(cmd_args)
|
||||
assert msg not in result.stdout_text
|
||||
--
|
||||
2.46.2
|
||||
|
209
0013-Don-t-rely-on-removing-the-CA-to-uninstall-the-ACME-.patch
Normal file
209
0013-Don-t-rely-on-removing-the-CA-to-uninstall-the-ACME-.patch
Normal file
@ -0,0 +1,209 @@
|
||||
From a785d0c561b8e22bd9d56739481095e07e0a7eb7 Mon Sep 17 00:00:00 2001
|
||||
From: Rob Crittenden <rcritten@redhat.com>
|
||||
Date: Mon, 30 Sep 2024 13:30:46 -0400
|
||||
Subject: [PATCH] Don't rely on removing the CA to uninstall the ACME depoyment
|
||||
|
||||
There has always been a pki-server commnd acme-remove. We were
|
||||
not aware that it should be called prior to removing a CA. In
|
||||
11.5.0 this is strongly encouraged by the PKI team. In 11.6.0
|
||||
ACME is treated as a full subsystem so will be removed in the
|
||||
future using pkidestroy -s ACME
|
||||
|
||||
The new class acmeinstance.ACMEInstance is introduced so its
|
||||
uninstallation can be handled in a similar way as the other
|
||||
PKI services via DogtagInstance. It is, right now, a pretty
|
||||
thin wrapper.
|
||||
|
||||
We can discuss moving the ACME installation routines here at
|
||||
some point. It would be ok as long as we don't have to introduce
|
||||
another PKI restart as part of it.
|
||||
|
||||
In PKI 11.6.0 pkidestroy has new options to ensure a clean
|
||||
uninstall: --remove-conf --remove-logs. Pass those options
|
||||
into pkidestroy calls for 11.6.0+.
|
||||
|
||||
Clean up an additional IPA-generated file that needs to be
|
||||
cleaned up during uninstall: /root/kracert.p12. 11.6.0 is
|
||||
more sensitive to leftover files than previous versions.
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9673
|
||||
Fixes: https://pagure.io/freeipa/issue/9674
|
||||
|
||||
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
ipaserver/install/acmeinstance.py | 31 +++++++++++++
|
||||
ipaserver/install/ca.py | 5 ++-
|
||||
ipaserver/install/cainstance.py | 1 +
|
||||
ipaserver/install/dogtaginstance.py | 44 +++++++++++++------
|
||||
.../test_integration/test_uninstallation.py | 21 +++++++++
|
||||
5 files changed, 87 insertions(+), 15 deletions(-)
|
||||
create mode 100644 ipaserver/install/acmeinstance.py
|
||||
|
||||
diff --git a/ipaserver/install/acmeinstance.py b/ipaserver/install/acmeinstance.py
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0027c314545f384d9b6ee24b279479e5360d8bef
|
||||
--- /dev/null
|
||||
+++ b/ipaserver/install/acmeinstance.py
|
||||
@@ -0,0 +1,31 @@
|
||||
+#
|
||||
+# Copyright (C) 2024 FreeIPA Contributors see COPYING for license
|
||||
+#
|
||||
+
|
||||
+import logging
|
||||
+
|
||||
+from ipaserver.install.dogtaginstance import DogtagInstance
|
||||
+
|
||||
+logger = logging.getLogger(__name__)
|
||||
+
|
||||
+
|
||||
+class ACMEInstance(DogtagInstance):
|
||||
+ """
|
||||
+ ACME is deployed automatically with a CA subsystem but it is the
|
||||
+ responsibility of IPA to uninstall the service.
|
||||
+
|
||||
+ This is mostly a placeholder for the uninstaller. We can
|
||||
+ eventually move the ACME installation routines into this class
|
||||
+ if we want but it might result in an extra PKI restart which
|
||||
+ would be slow.
|
||||
+ """
|
||||
+ def __init__(self, realm=None, host_name=None):
|
||||
+ super(ACMEInstance, self).__init__(
|
||||
+ realm=realm,
|
||||
+ subsystem="ACME",
|
||||
+ service_desc="ACME server",
|
||||
+ host_name=host_name
|
||||
+ )
|
||||
+
|
||||
+ def uninstall(self):
|
||||
+ DogtagInstance.uninstall(self)
|
||||
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
|
||||
index ffcb5268399ce71128fc8de5f54d433d35e99dd2..520e3fc5de1084e7c22c0cf7eaa86e1d3c421373 100644
|
||||
--- a/ipaserver/install/ca.py
|
||||
+++ b/ipaserver/install/ca.py
|
||||
@@ -22,7 +22,7 @@ from ipaplatform.constants import constants
|
||||
from ipaserver.install import sysupgrade
|
||||
from ipapython.install import typing
|
||||
from ipapython.install.core import group, knob, extend_knob
|
||||
-from ipaserver.install import cainstance, bindinstance, dsinstance
|
||||
+from ipaserver.install import acmeinstance, cainstance, bindinstance, dsinstance
|
||||
from ipapython import ipautil, certdb
|
||||
from ipapython import ipaldap
|
||||
from ipapython.admintool import ScriptError
|
||||
@@ -715,6 +715,9 @@ def install_step_1(standalone, replica_config, options, custodia):
|
||||
|
||||
|
||||
def uninstall():
|
||||
+ acme = acmeinstance.ACMEInstance(api.env.realm)
|
||||
+ acme.uninstall()
|
||||
+
|
||||
ca_instance = cainstance.CAInstance(api.env.realm)
|
||||
ca_instance.stop_tracking_certificates()
|
||||
ipautil.remove_file(paths.RA_AGENT_PEM)
|
||||
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
|
||||
index 5dac2c0441752e7bb569cde1fc93bc17c3128cdf..5c2c9f8b981cf5d587865f7680e2b231eae655e2 100644
|
||||
--- a/ipaserver/install/cainstance.py
|
||||
+++ b/ipaserver/install/cainstance.py
|
||||
@@ -1118,6 +1118,7 @@ class CAInstance(DogtagInstance):
|
||||
|
||||
ipautil.remove_file(paths.DOGTAG_ADMIN_P12)
|
||||
ipautil.remove_file(paths.CACERT_P12)
|
||||
+ ipautil.remove_file(paths.ADMIN_CERT_PATH)
|
||||
|
||||
def unconfigure_certmonger_renewal_guard(self):
|
||||
if not self.is_configured():
|
||||
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
|
||||
index e89492312deb8ca20668a62fd7a2a20e2866a3fb..4b0f4d274b0c33140ed6f939f1a3fd8b75930ff9 100644
|
||||
--- a/ipaserver/install/dogtaginstance.py
|
||||
+++ b/ipaserver/install/dogtaginstance.py
|
||||
@@ -304,21 +304,37 @@ class DogtagInstance(service.Service):
|
||||
if self.is_installed():
|
||||
self.print_msg("Unconfiguring %s" % self.subsystem)
|
||||
|
||||
- args = [paths.PKIDESTROY,
|
||||
- "-i", "pki-tomcat", "--force",
|
||||
- "-s", self.subsystem]
|
||||
-
|
||||
- # specify --log-file <path> on PKI 11.0.0 or later
|
||||
-
|
||||
+ args = []
|
||||
pki_version = pki.util.Version(pki.specification_version())
|
||||
- if pki_version >= pki.util.Version("11.0.0"):
|
||||
- timestamp = time.strftime(
|
||||
- "%Y%m%d%H%M%S",
|
||||
- time.localtime(time.time()))
|
||||
- log_file = os.path.join(
|
||||
- paths.VAR_LOG_PKI_DIR,
|
||||
- "pki-%s-destroy.%s.log" % (self.subsystem.lower(), timestamp))
|
||||
- args.extend(["--log-file", log_file])
|
||||
+ if self.subsystem == "ACME":
|
||||
+ if pki_version < pki.util.Version("11.0.0"):
|
||||
+ return
|
||||
+ elif (
|
||||
+ pki.util.Version("11.0.0") <= pki_version
|
||||
+ <= pki.util.Version("11.5.0")
|
||||
+ ):
|
||||
+ args = ['pki-server', 'acme-remove']
|
||||
+ else:
|
||||
+ # fall through for PKI >= 11.6.0
|
||||
+ pass
|
||||
+ if not args:
|
||||
+ args = [paths.PKIDESTROY,
|
||||
+ "-i", "pki-tomcat", "--force",
|
||||
+ "-s", self.subsystem]
|
||||
+
|
||||
+ # specify --log-file <path> on PKI 11.0.0 or later
|
||||
+
|
||||
+ if pki_version >= pki.util.Version("11.0.0"):
|
||||
+ timestamp = time.strftime(
|
||||
+ "%Y%m%d%H%M%S",
|
||||
+ time.localtime(time.time()))
|
||||
+ log_file = os.path.join(
|
||||
+ paths.VAR_LOG_PKI_DIR,
|
||||
+ "pki-%s-destroy.%s.log" %
|
||||
+ (self.subsystem.lower(), timestamp))
|
||||
+ args.extend(["--log-file", log_file])
|
||||
+ if pki_version >= pki.util.Version("11.6.0"):
|
||||
+ args.extend(["--remove-conf", "--remove-logs"])
|
||||
|
||||
try:
|
||||
ipautil.run(args)
|
||||
diff --git a/ipatests/test_integration/test_uninstallation.py b/ipatests/test_integration/test_uninstallation.py
|
||||
index 4f8f17ce3ad8d5376ecba11442f379e5691de7f7..049c50db536ae1070f5f958e76b12a1518da0aba 100644
|
||||
--- a/ipatests/test_integration/test_uninstallation.py
|
||||
+++ b/ipatests/test_integration/test_uninstallation.py
|
||||
@@ -197,6 +197,7 @@ class TestUninstallCleanup(IntegrationTest):
|
||||
'/var/lib/sss/pubconf/krb5.include.d/localauth_plugin',
|
||||
'/var/named/dynamic/managed-keys.bind',
|
||||
'/var/named/dynamic/managed-keys.bind.jnl',
|
||||
+ '/var/lib/systemd/coredump/',
|
||||
]
|
||||
|
||||
leftovers = []
|
||||
@@ -217,3 +218,23 @@ class TestUninstallCleanup(IntegrationTest):
|
||||
leftovers.append(line)
|
||||
|
||||
assert len(leftovers) == 0
|
||||
+
|
||||
+
|
||||
+class TestUninstallReinstall(IntegrationTest):
|
||||
+ """Test install, uninstall, re-install.
|
||||
+
|
||||
+ Reinstall with PKI 11.6.0 was failing
|
||||
+ https://pagure.io/freeipa/issue/9673
|
||||
+ """
|
||||
+
|
||||
+ num_replicas = 0
|
||||
+
|
||||
+ @classmethod
|
||||
+ def install(cls, mh):
|
||||
+ tasks.install_master(cls.master, setup_dns=False)
|
||||
+
|
||||
+ def test_uninstall_server(self):
|
||||
+ tasks.uninstall_master(self.master)
|
||||
+
|
||||
+ def test_reinstall_server(self):
|
||||
+ tasks.install_master(self.master, setup_dns=False)
|
||||
--
|
||||
2.46.2
|
||||
|
35
0014-ipatests-Fixes-for-ipa-idrange-fix-testsuite.patch
Normal file
35
0014-ipatests-Fixes-for-ipa-idrange-fix-testsuite.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From ae4c2ad6cd966d48c063814f494dcc16cf0ccd4c Mon Sep 17 00:00:00 2001
|
||||
From: Sudhir Menon <sumenon@redhat.com>
|
||||
Date: Tue, 24 Sep 2024 13:46:48 +0530
|
||||
Subject: [PATCH] ipatests: Fixes for ipa-idrange-fix testsuite
|
||||
|
||||
This patch adds the line tasks.install_master(cls.master).
|
||||
The kinit admin command fails with the below error as the
|
||||
IPA is not configured on the test system
|
||||
|
||||
'ipa: ERROR: stderr: kinit: Configuration file does not specify default
|
||||
realm when parsing name admin'
|
||||
|
||||
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
---
|
||||
ipatests/test_integration/test_ipa_idrange_fix.py | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_ipa_idrange_fix.py b/ipatests/test_integration/test_ipa_idrange_fix.py
|
||||
index ff8fbdac9d028d26fc55f5e357f89af879a61723..0c915bd0931ed11a3aa86c533ee8748aa8a7ec07 100644
|
||||
--- a/ipatests/test_integration/test_ipa_idrange_fix.py
|
||||
+++ b/ipatests/test_integration/test_ipa_idrange_fix.py
|
||||
@@ -17,6 +17,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestIpaIdrangeFix(IntegrationTest):
|
||||
+
|
||||
+ topology = 'line'
|
||||
+
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
super(TestIpaIdrangeFix, cls).install(mh)
|
||||
--
|
||||
2.46.2
|
||||
|
265
0015-Do-not-let-user-with-an-expired-OTP-token-to-log-in-.patch
Normal file
265
0015-Do-not-let-user-with-an-expired-OTP-token-to-log-in-.patch
Normal file
@ -0,0 +1,265 @@
|
||||
From 18303b94bea4e08a0c889fc357df6ba2f308fa0d Mon Sep 17 00:00:00 2001
|
||||
From: Mark Reynolds <mreynolds@redhat.com>
|
||||
Date: Wed, 2 Oct 2024 21:26:34 -0400
|
||||
Subject: [PATCH] Do not let user with an expired OTP token to log in if only
|
||||
OTP is allowed
|
||||
|
||||
If only OTP authentication is allowed, and a user tries to login with an
|
||||
expired token, do not let them log in with their password. Forcing the
|
||||
admin to intervene. If the user does not have an OTP token then allow
|
||||
them to log in with a password until an OTP token is configured
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9387
|
||||
|
||||
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
Reviewed-By: Julien Rische <jrische@redhat.com>
|
||||
---
|
||||
daemons/ipa-kdb/ipa_kdb_principals.c | 63 +++++++++++--
|
||||
.../ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 3 +-
|
||||
ipatests/test_integration/test_otp.py | 94 ++++++++++++++++++-
|
||||
3 files changed, 151 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
|
||||
index 14603e528b43acb29234c425e97ad297ac6724a7..114957b884786dd3ca3b01c47f6bb82e8a040beb 100644
|
||||
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
|
||||
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
|
||||
@@ -107,7 +107,6 @@ static char *std_principal_obj_classes[] = {
|
||||
"krbprincipal",
|
||||
"krbprincipalaux",
|
||||
"krbTicketPolicyAux",
|
||||
-
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -338,14 +337,16 @@ static void ipadb_validate_otp(struct ipadb_context *ipactx,
|
||||
if (dn == NULL)
|
||||
return;
|
||||
count = asprintf(&filter, ftmpl, dn, datetime, datetime);
|
||||
- ldap_memfree(dn);
|
||||
- if (count < 0)
|
||||
+ if (count < 0) {
|
||||
+ ldap_memfree(dn);
|
||||
return;
|
||||
+ }
|
||||
|
||||
/* Fetch the active token list. */
|
||||
kerr = ipadb_simple_search(ipactx, ipactx->base, LDAP_SCOPE_SUBTREE,
|
||||
filter, (char**) attrs, &res);
|
||||
free(filter);
|
||||
+ filter = NULL;
|
||||
if (kerr != 0 || res == NULL)
|
||||
return;
|
||||
|
||||
@@ -353,10 +354,60 @@ static void ipadb_validate_otp(struct ipadb_context *ipactx,
|
||||
count = ldap_count_entries(ipactx->lcontext, res);
|
||||
ldap_msgfree(res);
|
||||
|
||||
- /* If the user is configured for OTP, but has no active tokens, remove
|
||||
- * OTP from the list since the user obviously can't log in this way. */
|
||||
- if (count == 0)
|
||||
+ /*
|
||||
+ * If there are no valid tokens then we need to remove the OTP flag,
|
||||
+ * unless OTP is the only auth type allowed...
|
||||
+ */
|
||||
+ if (count == 0) {
|
||||
+ /* Remove the OTP flag for now */
|
||||
*ua &= ~IPADB_USER_AUTH_OTP;
|
||||
+
|
||||
+ if (*ua == 0) {
|
||||
+ /*
|
||||
+ * Ok, we "only" allow OTP, so if there is an expired/disabled
|
||||
+ * token then add back the OTP flag as the server will double
|
||||
+ * check the validity and reject the entire bind. Otherwise, this
|
||||
+ * is the first time the user is authenticating and the user
|
||||
+ * should be allowed to bind using its password
|
||||
+ */
|
||||
+ static const char *expired_ftmpl = "(&"
|
||||
+ "(objectClass=ipaToken)(ipatokenOwner=%s)"
|
||||
+ "(|(ipatokenNotAfter<=%s)(!(ipatokenNotAfter=*))"
|
||||
+ "(ipatokenDisabled=True))"
|
||||
+ ")";
|
||||
+ if (asprintf(&filter, expired_ftmpl, dn, datetime) < 0) {
|
||||
+ ldap_memfree(dn);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ krb5_klog_syslog(LOG_INFO,
|
||||
+ "Entry (%s) does not have a valid token and only OTP "
|
||||
+ "authentication is supported, checking for expired tokens...",
|
||||
+ dn);
|
||||
+
|
||||
+ kerr = ipadb_simple_search(ipactx, ipactx->base, LDAP_SCOPE_SUBTREE,
|
||||
+ filter, (char**) attrs, &res);
|
||||
+ free(filter);
|
||||
+ if (kerr != 0 || res == NULL) {
|
||||
+ ldap_memfree(dn);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (ldap_count_entries(ipactx->lcontext, res) > 0) {
|
||||
+ /*
|
||||
+ * Ok we only allow OTP, and there are expired/disabled tokens
|
||||
+ * so add the OTP flag back, and the server will reject the
|
||||
+ * bind
|
||||
+ */
|
||||
+ krb5_klog_syslog(LOG_INFO,
|
||||
+ "Entry (%s) does have an expired/disabled token so this "
|
||||
+ "user can not fall through to password auth", dn);
|
||||
+ *ua |= IPADB_USER_AUTH_OTP;
|
||||
+ }
|
||||
+ ldap_msgfree(res);
|
||||
+ }
|
||||
+ }
|
||||
+ ldap_memfree(dn);
|
||||
}
|
||||
|
||||
static void ipadb_validate_radius(struct ipadb_context *ipactx,
|
||||
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
|
||||
index c967e2cfffbd920280639f3188783ec150523b47..1c1340e31ac30cb01412a7065ea339cb5461e839 100644
|
||||
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
|
||||
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
|
||||
@@ -1528,7 +1528,8 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
if (!syncreq && (otpreq == OTP_IS_NOT_REQUIRED)) {
|
||||
ret = ipapwd_gen_checks(pb, &errMesg, &krbcfg, IPAPWD_CHECK_ONLY_CONFIG);
|
||||
if (ret != 0) {
|
||||
- LOG_FATAL("ipapwd_gen_checks failed!?\n");
|
||||
+ LOG_FATAL("ipapwd_gen_checks failed for '%s': %s\n",
|
||||
+ slapi_sdn_get_dn(sdn), errMesg);
|
||||
slapi_entry_free(entry);
|
||||
slapi_sdn_free(&sdn);
|
||||
return 0;
|
||||
diff --git a/ipatests/test_integration/test_otp.py b/ipatests/test_integration/test_otp.py
|
||||
index 350371bfe1e4c1cc6dcc89f6584f813fcb0d32a0..878b4fb560ba8d7768ead54b065656462545babd 100644
|
||||
--- a/ipatests/test_integration/test_otp.py
|
||||
+++ b/ipatests/test_integration/test_otp.py
|
||||
@@ -10,6 +10,7 @@ import re
|
||||
import time
|
||||
import textwrap
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
+from paramiko import AuthenticationException
|
||||
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
@@ -83,7 +84,7 @@ def kinit_otp(host, user, *, password, otp, success=True):
|
||||
)
|
||||
|
||||
|
||||
-def ssh_2f(hostname, username, answers_dict, port=22):
|
||||
+def ssh_2f(hostname, username, answers_dict, port=22, unwanted_prompt=""):
|
||||
"""
|
||||
:param hostname: hostname
|
||||
:param username: username
|
||||
@@ -103,6 +104,10 @@ def ssh_2f(hostname, username, answers_dict, port=22):
|
||||
logger.info("Prompt is: '%s'", prmpt_str)
|
||||
logger.info(
|
||||
"Answer to ssh prompt is: '%s'", answers_dict[prmpt_str])
|
||||
+ if unwanted_prompt and prmpt_str == unwanted_prompt:
|
||||
+ # We should not see this prompt
|
||||
+ raise ValueError("We got an unwanted prompt: "
|
||||
+ + answers_dict[prmpt_str])
|
||||
return resp
|
||||
|
||||
import paramiko
|
||||
@@ -193,7 +198,8 @@ class TestOTPToken(IntegrationTest):
|
||||
|
||||
# skipping too many OTP fails
|
||||
otp1 = hotp.generate(10).decode("ascii")
|
||||
- kinit_otp(self.master, USER, password=PASSWORD, otp=otp1, success=False)
|
||||
+ kinit_otp(self.master, USER, password=PASSWORD, otp=otp1,
|
||||
+ success=False)
|
||||
# Now the token is desynchronized
|
||||
yield (otpuid, hotp)
|
||||
|
||||
@@ -536,3 +542,87 @@ class TestOTPToken(IntegrationTest):
|
||||
finally:
|
||||
master.run_command(['ipa', 'pwpolicy-mod', '--minlife', '1'])
|
||||
master.run_command(['ipa', 'user-del', USER1])
|
||||
+
|
||||
+ def test_totp_expired_ldap(self):
|
||||
+ master = self.master
|
||||
+ basedn = master.domain.basedn
|
||||
+ USER1 = 'user-expired-otp'
|
||||
+ TMP_PASSWORD = 'Secret1234509'
|
||||
+ binddn = DN(f"uid={USER1},cn=users,cn=accounts,{basedn}")
|
||||
+ controls = [
|
||||
+ BooleanControl(
|
||||
+ controlType="2.16.840.1.113730.3.8.10.7",
|
||||
+ booleanValue=True)
|
||||
+ ]
|
||||
+
|
||||
+ tasks.kinit_admin(master)
|
||||
+ master.run_command(['ipa', 'pwpolicy-mod', '--minlife', '0'])
|
||||
+ tasks.user_add(master, USER1, password=TMP_PASSWORD)
|
||||
+ # Enforce use of OTP token for this user
|
||||
+ master.run_command(['ipa', 'user-mod', USER1,
|
||||
+ '--user-auth-type=otp'])
|
||||
+ try:
|
||||
+ # Change initial password through the IPA endpoint
|
||||
+ url = f'https://{master.hostname}/ipa/session/change_password'
|
||||
+ master.run_command(['curl', '-d', f'user={USER1}',
|
||||
+ '-d', f'old_password={TMP_PASSWORD}',
|
||||
+ '-d', f'new_password={PASSWORD}',
|
||||
+ '--referer', f'https://{master.hostname}/ipa',
|
||||
+ url])
|
||||
+ conn = master.ldap_connect()
|
||||
+ # First, attempt authenticating with a password but without LDAP
|
||||
+ # control to enforce OTP presence and without server-side
|
||||
+ # enforcement of the OTP presence check.
|
||||
+ conn.simple_bind(binddn, f"{PASSWORD}")
|
||||
+
|
||||
+ # Add an OTP token and then modify it to be expired
|
||||
+ otpuid, totp = add_otptoken(master, USER1, otptype="totp")
|
||||
+
|
||||
+ # Make sure OTP auth is working
|
||||
+ otpvalue = totp.generate(int(time.time())).decode("ascii")
|
||||
+ conn = master.ldap_connect()
|
||||
+ conn.simple_bind(binddn, f"{PASSWORD}{otpvalue}",
|
||||
+ client_controls=controls)
|
||||
+ conn.unbind()
|
||||
+
|
||||
+ # Modfy token so that is now expired
|
||||
+ args = [
|
||||
+ "ipa",
|
||||
+ "otptoken-mod",
|
||||
+ otpuid,
|
||||
+ "--not-after",
|
||||
+ "20241001010000Z",
|
||||
+ ]
|
||||
+ master.run_command(args)
|
||||
+
|
||||
+ # Next, authenticate with Password+OTP again and with the LDAP
|
||||
+ # control this operation should now fail
|
||||
+ time.sleep(45)
|
||||
+ otpvalue = totp.generate(int(time.time())).decode("ascii")
|
||||
+
|
||||
+ conn = master.ldap_connect()
|
||||
+ with pytest.raises(errors.ACIError):
|
||||
+ conn.simple_bind(binddn, f"{PASSWORD}{otpvalue}",
|
||||
+ client_controls=controls)
|
||||
+
|
||||
+ # Sleep to make sure we are going to use a different token value
|
||||
+ time.sleep(45)
|
||||
+
|
||||
+ # Use OTP token again but authenticate over ssh and make sure it
|
||||
+ # doesn't fallthrough to asking for a password
|
||||
+ otpvalue = totp.generate(int(time.time())).decode("ascii")
|
||||
+ answers = {
|
||||
+ 'Enter first factor:': PASSWORD,
|
||||
+ 'Enter second factor:': otpvalue
|
||||
+ }
|
||||
+ with pytest.raises(AuthenticationException):
|
||||
+ # ssh should fail and NOT ask for a password
|
||||
+ ssh_2f(master.hostname, USER1, answers,
|
||||
+ unwanted_prompt="Password:")
|
||||
+
|
||||
+ # Remove token
|
||||
+ del_otptoken(self.master, otpuid)
|
||||
+
|
||||
+ finally:
|
||||
+ master.run_command(['ipa', 'pwpolicy-mod', '--minlife', '1'])
|
||||
+ master.run_command(['ipa', 'user-del', USER1])
|
||||
--
|
||||
2.46.2
|
||||
|
41
0016-ipatests-Activate-ssh-in-sssd.conf.patch
Normal file
41
0016-ipatests-Activate-ssh-in-sssd.conf.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From 761647f842567713032709753b6d63467d9871a6 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhir Menon <sumenon@redhat.com>
|
||||
Date: Mon, 23 Sep 2024 14:05:43 +0530
|
||||
Subject: [PATCH] ipatests: Activate ssh in sssd.conf
|
||||
|
||||
This testcase checks that services: ssh
|
||||
is included in the sssd.conf file when
|
||||
ipa-client-install is successful.
|
||||
|
||||
Ref: https://pagure.io/freeipa/issue/9649
|
||||
|
||||
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
---
|
||||
ipatests/test_integration/test_installation_client.py | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_installation_client.py b/ipatests/test_integration/test_installation_client.py
|
||||
index f8567b39eead4dffd522aad504fa72a086969257..884bff2f2f3e49f66da391424e128d8e31b82a8a 100644
|
||||
--- a/ipatests/test_integration/test_installation_client.py
|
||||
+++ b/ipatests/test_integration/test_installation_client.py
|
||||
@@ -94,6 +94,16 @@ class TestInstallClient(IntegrationTest):
|
||||
).encode() not in krb5_cfg
|
||||
tasks.uninstall_client(self.clients[0])
|
||||
|
||||
+ def test_check_ssh_service_is_activated(self):
|
||||
+ """
|
||||
+ This test checks all default services are activated
|
||||
+ in sssd.conf including ssh
|
||||
+ """
|
||||
+ tasks.install_client(self.master, self.clients[0])
|
||||
+ sssd_cfg = self.clients[0].get_file_contents(paths.SSSD_CONF)
|
||||
+ assert 'services = nss, pam, ssh, sudo' in sssd_cfg.decode()
|
||||
+ tasks.uninstall_client(self.clients[0])
|
||||
+
|
||||
def test_install_with_automount(self):
|
||||
"""Test that installation with automount is successful"""
|
||||
tasks.install_client(self.master, self.clients[0],
|
||||
--
|
||||
2.46.2
|
||||
|
131
0017-ipa-migrate-man-page-fix-typos-and-errors.patch
Normal file
131
0017-ipa-migrate-man-page-fix-typos-and-errors.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From f978fa05e3ed9d4ad9d20493c05c77fb9b4976a7 Mon Sep 17 00:00:00 2001
|
||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Date: Tue, 15 Oct 2024 17:04:55 +0200
|
||||
Subject: [PATCH] ipa-migrate man page: fix typos and errors
|
||||
|
||||
ipa-migrate man page mentions non-existing option --hostname.
|
||||
Fix the SYNOPSIS and various typos.
|
||||
|
||||
Fixes: https://pagure.io/freeipa/issue/9681
|
||||
|
||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||
Reviewed-By: Mark Reynolds <mreynolds@redhat.com>
|
||||
---
|
||||
install/tools/man/ipa-migrate.1 | 38 +++++++++++++++------------------
|
||||
1 file changed, 17 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/install/tools/man/ipa-migrate.1 b/install/tools/man/ipa-migrate.1
|
||||
index 47ae47ea4afa3a5a6fe25dd9bbd14c27ab5f1fdb..5106f4f0f5b5928909ccd5abcef3bb6d1586f5df 100644
|
||||
--- a/install/tools/man/ipa-migrate.1
|
||||
+++ b/install/tools/man/ipa-migrate.1
|
||||
@@ -5,11 +5,11 @@
|
||||
.SH "NAME"
|
||||
ipa\-migrate \- Migrate an IPA server from one machine to another
|
||||
.SH "SYNOPSIS"
|
||||
-ipa\-migrate
|
||||
+\fBipa\-migrate\fR [OPTIONS] \fBprod\-mode\fR|\fBstage\-mode\fR \fIhostname\fR
|
||||
.SH "DESCRIPTION"
|
||||
|
||||
Use the \fIipa-migrate\fR command to migrate one
|
||||
-IPA server to an existing local IPA server installation.
|
||||
+IPA server \fIhostname\fR to an existing local IPA server installation.
|
||||
|
||||
Migrate IPA schema, configuration, and database to a local IPA server. This
|
||||
migration can be done online, where the tool will query the remote server. Or,
|
||||
@@ -19,7 +19,6 @@ and then use an exported LDIF file for the database migration portion (this
|
||||
might be more useful for very large databases as you don't need to worry about
|
||||
network interruptions)
|
||||
|
||||
-.SH POSITIONAL ARGUMENTS
|
||||
.TP
|
||||
\fBprod\-mode\fR
|
||||
In this mode everything will be migrated including the current user SIDs and
|
||||
@@ -28,13 +27,10 @@ DNA ranges
|
||||
\fBstage\-mode\fR
|
||||
In this mode, SIDs & DNA ranges are not migrated, and DNA attributes are reset
|
||||
|
||||
-.SH "COMMANDS"
|
||||
+.SH "OPTIONS"
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-verbose\fR
|
||||
-Use verbose output while running the migration tool.
|
||||
-.TP
|
||||
-\fB\-e\fR, \fB\-\-hostname=HOSTNAME\fR
|
||||
-The host name of the remote IPA server that is being migrated from.
|
||||
+Use verbose output while running the migration tool
|
||||
.TP
|
||||
\fB\-D\fR, \fB\-\-bind\-dn=BIND_DN\fR
|
||||
The Bind DN (Distinguished Name) or an LDAP entry to bind to the remote IPA server with.
|
||||
@@ -43,10 +39,10 @@ access to read the userPassword attribute. If ommitted the default is "cn=direc
|
||||
.TP
|
||||
\fB\-w\fR, \fB\-\-bind\-pw=PASSWORD\fR
|
||||
The password for the Bind DN that is authenticating against the remote IPA server. If
|
||||
-a password is not provided then the tool with prompt for the password if needed.
|
||||
+a password is not provided then the tool with prompt for the password if needed
|
||||
.TP
|
||||
-\fB\-Just\fR, \fB\-\-bind\-pw\-file=FILE_PATH\fR
|
||||
-Path to a file containing the password for the Bind DN.
|
||||
+\fB\-j\fR, \fB\-\-bind\-pw\-file=FILE_PATH\fR
|
||||
+Path to a file containing the password for the Bind DN
|
||||
.TP
|
||||
\fB\-Z\fR, \fB\-\-cacertfile=FILE_PATH\fR
|
||||
Path to a file containing a CA Certificate that the remote server trusts
|
||||
@@ -55,23 +51,23 @@ Path to a file containing a CA Certificate that the remote server trusts
|
||||
Path to a file containing the migration log. By default the tool will use \fI/var/log/ipa-migrate.log\fR
|
||||
.TP
|
||||
\fB\-x\fR, \fB\-\-dryrun\fR
|
||||
-Go through the migration process but do not write and data to the new IPA server.
|
||||
+Go through the migration process but do not write any data to the new IPA server
|
||||
.TP
|
||||
\fB\-o\fR, \fB\-\-dryrun\-record=FILE_PATH\fR
|
||||
Go through the migration process but do not write any data to the new IPA server. However, write the
|
||||
-migration operations to an LDIF file which can be applied later or reused for multiple migrations.
|
||||
+migration operations to an LDIF file which can be applied later or reused for multiple migrations
|
||||
.TP
|
||||
\fB\-r\fR, \fB\-\-reset\-range\fR
|
||||
Reset the ID range for migrated users/groups. In "stage-mode" this is done automatically
|
||||
.TP
|
||||
\fB\-F\fR, \fB\-\-force\fR
|
||||
-Ignore any errors and continue to proceed with migration effort.
|
||||
+Ignore any errors and continue to proceed with migration effort
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
-Only log errors during the migration process.
|
||||
+Only log errors during the migration process
|
||||
.TP
|
||||
\fB\-B\fR, \fB\-\-migrate\-dns\fR
|
||||
-Migrate thr DNS records
|
||||
+Migrate the DNS records
|
||||
.TP
|
||||
\fB\-S\fR, \fB\-\-skip\-schema\fR
|
||||
Do not migrate the database schema
|
||||
@@ -80,21 +76,21 @@ Do not migrate the database schema
|
||||
Do not migrate the database configuration (dse.ldif/cn=config)
|
||||
.TP
|
||||
\fB\-O\fR, \fB\-\-schema\-overwrite\fR
|
||||
-Overwrite existing schema definitions. By default duplicate schema is skipped.
|
||||
+Overwrite existing schema definitions. By default duplicate schema is skipped
|
||||
.TP
|
||||
\fB\-s\fR, \fB\-\-subtree=DN\fR
|
||||
Specifies a custom database subtree that should be included in the migration.
|
||||
This is only needed if non-default subtrees/branches were added to the database
|
||||
-outside of IPA.
|
||||
+outside of IPA
|
||||
.TP
|
||||
\fB\-f\fR, \fB\-\-db\-ldif=FILE_PATH\fR
|
||||
-LDIF file containing the entire backend. If omitted the tool will query the remote IPA server.
|
||||
+LDIF file containing the entire backend. If omitted the tool will query the remote IPA server
|
||||
.TP
|
||||
\fB\-m\fR, \fB\-\-schema\-ldif=FILE_PATH\fR
|
||||
-LDIF file containing the schema. If omitted the tool will query the remote IPA server.
|
||||
+LDIF file containing the schema. If omitted the tool will query the remote IPA server
|
||||
.TP
|
||||
\fB\-g\fR, \fB\-\-config\-ldif=FILE_PATH\fR
|
||||
-LDIF file containing the entire "cn=config" DIT. If omitted the tool will query the remote IPA server.
|
||||
+LDIF file containing the entire "cn=config" DIT. If omitted the tool will query the remote IPA server
|
||||
.TP
|
||||
\fB\-n\fR, \fB\-\-no\-prompt\fR
|
||||
Do not prompt for confirmation before starting migration. Use at your own risk!
|
||||
--
|
||||
2.46.2
|
||||
|
61
0018-ipatests-Test-for-ipa-hbac-rule-duplication.patch
Normal file
61
0018-ipatests-Test-for-ipa-hbac-rule-duplication.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 7f4e7e1d6a2ae9d05a2dfcf620f4df07d09d9d2b Mon Sep 17 00:00:00 2001
|
||||
From: Sudhir Menon <sumenon@redhat.com>
|
||||
Date: Thu, 3 Oct 2024 18:45:31 +0530
|
||||
Subject: [PATCH] ipatests: Test for ipa hbac rule duplication
|
||||
|
||||
This test checks that ipa-migrate is not creating duplicate default hbac rules
|
||||
for allow_all and allow_systemd-user rules.
|
||||
|
||||
Related: https://pagure.io/freeipa/issue/9640
|
||||
|
||||
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||
---
|
||||
.../test_ipa_ipa_migration.py | 26 +++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_ipa_ipa_migration.py b/ipatests/test_integration/test_ipa_ipa_migration.py
|
||||
index 288165e8a83a96e6f6bd4e52866f98617f497c56..70c268951a0d7e40806742b16e62b764b2bae37b 100644
|
||||
--- a/ipatests/test_integration/test_ipa_ipa_migration.py
|
||||
+++ b/ipatests/test_integration/test_ipa_ipa_migration.py
|
||||
@@ -9,6 +9,7 @@ from __future__ import absolute_import
|
||||
from ipatests.test_integration.base import IntegrationTest
|
||||
from ipatests.pytest_ipa.integration import tasks
|
||||
from ipaplatform.paths import paths
|
||||
+from collections import Counter
|
||||
|
||||
import pytest
|
||||
import textwrap
|
||||
@@ -920,3 +921,28 @@ class TestIPAMigrateScenario1(IntegrationTest):
|
||||
)
|
||||
assert result.returncode == 1
|
||||
assert ERR_MSG in result.stderr_text
|
||||
+
|
||||
+ def test_ipa_hbac_rule_duplication(self):
|
||||
+ """
|
||||
+ This testcase checks that default hbac rules
|
||||
+ are not duplicated on the local server when
|
||||
+ ipa-migrate command is run.
|
||||
+ """
|
||||
+ run_migrate(
|
||||
+ self.replicas[0],
|
||||
+ "prod-mode",
|
||||
+ self.master.hostname,
|
||||
+ "cn=Directory Manager",
|
||||
+ self.master.config.admin_password,
|
||||
+ extra_args=['-n']
|
||||
+ )
|
||||
+ result = self.replicas[0].run_command(
|
||||
+ ['ipa', 'hbacrule-find']
|
||||
+ )
|
||||
+ lines = result.stdout_text.splitlines()
|
||||
+ line = []
|
||||
+ for i in lines:
|
||||
+ line.append(i.strip())
|
||||
+ count = Counter(line)
|
||||
+ assert count.get('Rule name: allow_all') < 2
|
||||
+ assert count.get('Rule name: allow_systemd-user') < 2
|
||||
--
|
||||
2.46.2
|
||||
|
116
0019-ipatests-refactor-password-file-handling-in-TestHSMI.patch
Normal file
116
0019-ipatests-refactor-password-file-handling-in-TestHSMI.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From 142f52fc981fe9f1d693b79a7b49506af2e98829 Mon Sep 17 00:00:00 2001
|
||||
From: Mohammad Rizwan <myusuf@redhat.com>
|
||||
Date: Mon, 19 Aug 2024 16:08:53 +0530
|
||||
Subject: [PATCH] ipatests: refactor password file handling in TestHSMInstall
|
||||
|
||||
When token and associated certs are not being cleaned
|
||||
up properly, the subsequent installation fails. Hence
|
||||
Password file related scenarios moved out to new test class
|
||||
so that it have fresh installation.
|
||||
|
||||
Signed-off-by: Mohammad Rizwan <myusuf@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||
---
|
||||
.../nightly_ipa-4-12_latest.yaml | 12 ++++++++
|
||||
.../nightly_ipa-4-12_latest_selinux.yaml | 13 ++++++++
|
||||
ipatests/test_integration/test_hsm.py | 30 ++++++++++---------
|
||||
3 files changed, 41 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/ipatests/prci_definitions/nightly_ipa-4-12_latest.yaml b/ipatests/prci_definitions/nightly_ipa-4-12_latest.yaml
|
||||
index 6d18e708fb0512ce21d8db68d4f1ab26849f40b7..07e2a8399ae4cc953adb415b975101ed20c67fd2 100644
|
||||
--- a/ipatests/prci_definitions/nightly_ipa-4-12_latest.yaml
|
||||
+++ b/ipatests/prci_definitions/nightly_ipa-4-12_latest.yaml
|
||||
@@ -1950,6 +1950,18 @@ jobs:
|
||||
timeout: 6300
|
||||
topology: *master_3repl_1client
|
||||
|
||||
+ fedora-latest-ipa-4-12/test_hsm_TestHSMInstallPasswordFile:
|
||||
+ requires: [fedora-latest-ipa-4-12/build]
|
||||
+ priority: 50
|
||||
+ job:
|
||||
+ class: RunPytest
|
||||
+ args:
|
||||
+ build_url: '{fedora-latest-ipa-4-12/build_url}'
|
||||
+ test_suite: test_integration/test_hsm.py::TestHSMInstallPasswordFile
|
||||
+ template: *ci-ipa-4-12-latest
|
||||
+ timeout: 6300
|
||||
+ topology: *master_1repl
|
||||
+
|
||||
fedora-latest-ipa-4-12/test_hsm_TestHSMInstallADTrustBase:
|
||||
requires: [fedora-latest-ipa-4-12/build]
|
||||
priority: 50
|
||||
diff --git a/ipatests/prci_definitions/nightly_ipa-4-12_latest_selinux.yaml b/ipatests/prci_definitions/nightly_ipa-4-12_latest_selinux.yaml
|
||||
index 52686df9713975c9590b8a99edb7c3442531fecc..11046be13fca1e7403d0fd74329a66ded3927a6c 100644
|
||||
--- a/ipatests/prci_definitions/nightly_ipa-4-12_latest_selinux.yaml
|
||||
+++ b/ipatests/prci_definitions/nightly_ipa-4-12_latest_selinux.yaml
|
||||
@@ -2105,6 +2105,19 @@ jobs:
|
||||
timeout: 6300
|
||||
topology: *master_3repl_1client
|
||||
|
||||
+ fedora-latest-ipa-4-12/test_hsm_TestHSMInstallPasswordFile:
|
||||
+ requires: [fedora-latest-ipa-4-12/build]
|
||||
+ priority: 50
|
||||
+ job:
|
||||
+ class: RunPytest
|
||||
+ args:
|
||||
+ build_url: '{fedora-latest-ipa-4-12/build_url}'
|
||||
+ selinux_enforcing: True
|
||||
+ test_suite: test_integration/test_hsm.py::TestHSMInstallPasswordFile
|
||||
+ template: *ci-ipa-4-12-latest
|
||||
+ timeout: 6300
|
||||
+ topology: *master_1repl
|
||||
+
|
||||
fedora-latest-ipa-4-12/test_hsm_TestHSMInstallADTrustBase:
|
||||
requires: [fedora-latest-ipa-4-12/build]
|
||||
priority: 50
|
||||
diff --git a/ipatests/test_integration/test_hsm.py b/ipatests/test_integration/test_hsm.py
|
||||
index 374f5c25fd3453cd45a15d2b0f20cee424282595..42895fcd60a7c02d3b6103c2f6751a367da30b2f 100644
|
||||
--- a/ipatests/test_integration/test_hsm.py
|
||||
+++ b/ipatests/test_integration/test_hsm.py
|
||||
@@ -312,24 +312,26 @@ class TestHSMInstall(BaseHSMTest):
|
||||
assert returncode == 0
|
||||
assert output == "No issues found."
|
||||
|
||||
- def test_hsm_install_server_password_file(self):
|
||||
- check_version(self.master)
|
||||
- # cleanup before fresh install with password file
|
||||
- for client in self.clients:
|
||||
- tasks.uninstall_client(client)
|
||||
|
||||
- for replica in self.replicas:
|
||||
- tasks.uninstall_master(replica)
|
||||
+class TestHSMInstallPasswordFile(BaseHSMTest):
|
||||
|
||||
- tasks.uninstall_master(self.master)
|
||||
+ num_replicas = 1
|
||||
|
||||
- delete_hsm_token([self.master] + self.replicas, self.token_name)
|
||||
- self.token_name, self.token_password = get_hsm_token(self.master)
|
||||
- self.master.put_file_contents(self.token_password_file,
|
||||
- self.token_password)
|
||||
- self.replicas[0].put_file_contents(self.token_password_file,
|
||||
- self.token_password)
|
||||
+ @classmethod
|
||||
+ def install(cls, mh):
|
||||
+ check_version(cls.master)
|
||||
+ # Enable pkiuser to read softhsm tokens
|
||||
+ cls.master.run_command(['usermod', 'pkiuser', '-a', '-G', 'ods'])
|
||||
+ cls.token_name, cls.token_password = get_hsm_token(cls.master)
|
||||
+ cls.master.put_file_contents(
|
||||
+ cls.token_password_file, cls.token_password
|
||||
+ )
|
||||
+ cls.replicas[0].put_file_contents(
|
||||
+ cls.token_password_file, cls.token_password
|
||||
+ )
|
||||
|
||||
+ def test_hsm_install_server_password_file(self):
|
||||
+ check_version(self.master)
|
||||
tasks.install_master(
|
||||
self.master, setup_dns=self.master_with_dns,
|
||||
setup_kra=self.master_with_kra,
|
||||
--
|
||||
2.46.2
|
||||
|
276
0020-ipatests-2FA-test-cases.patch
Normal file
276
0020-ipatests-2FA-test-cases.patch
Normal file
@ -0,0 +1,276 @@
|
||||
From 6ac11ae003740faf19f3c75bf542ec44f717114f Mon Sep 17 00:00:00 2001
|
||||
From: Madhuri Upadhye <mupadhye@redhat.com>
|
||||
Date: Tue, 23 Jul 2024 18:14:36 +0530
|
||||
Subject: [PATCH] ipatests: 2FA test cases
|
||||
|
||||
Added following:
|
||||
|
||||
Added 'ssh_2fa_with_cmd' method for authentication,
|
||||
as for '\n' with paramiko did not work. In a test case
|
||||
need to just press `Enter` for `second factor`.
|
||||
Advantage of above function is no having paramiko
|
||||
dependancy.
|
||||
We can run the any command in same session after
|
||||
authentication of user.
|
||||
|
||||
Test cases:
|
||||
1. Authenticate the user only with password,
|
||||
just press enter at `Second factor` and check tgt after auth.
|
||||
when User authentication types: otp, password
|
||||
2. Authenticate the user with password and otpvalues and
|
||||
check tgt of user after auth when
|
||||
User authentication types: otp, password
|
||||
|
||||
related: https://github.com/SSSD/sssd/pull/7500
|
||||
|
||||
Signed-off-by: Madhuri Upadhye <mupadhye@redhat.com>
|
||||
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||
---
|
||||
ipatests/test_integration/test_otp.py | 192 ++++++++++++++++++++++++--
|
||||
1 file changed, 181 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/ipatests/test_integration/test_otp.py b/ipatests/test_integration/test_otp.py
|
||||
index 878b4fb560ba8d7768ead54b065656462545babd..0babb45897c6107bf354477dbb0d3a805a3116f5 100644
|
||||
--- a/ipatests/test_integration/test_otp.py
|
||||
+++ b/ipatests/test_integration/test_otp.py
|
||||
@@ -5,26 +5,27 @@
|
||||
"""
|
||||
import base64
|
||||
import logging
|
||||
-import pytest
|
||||
import re
|
||||
-import time
|
||||
+import tempfile
|
||||
import textwrap
|
||||
-from urllib.parse import urlparse, parse_qs
|
||||
-from paramiko import AuthenticationException
|
||||
+import time
|
||||
+from urllib.parse import parse_qs, urlparse
|
||||
|
||||
+import pytest
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.twofactor.hotp import HOTP
|
||||
from cryptography.hazmat.primitives.twofactor.totp import TOTP
|
||||
-
|
||||
-from ipatests.test_integration.base import IntegrationTest
|
||||
-from ipaplatform.paths import paths
|
||||
-from ipatests.pytest_ipa.integration import tasks
|
||||
-from ipapython.dn import DN
|
||||
-
|
||||
from ldap.controls.simple import BooleanControl
|
||||
+from paramiko import AuthenticationException
|
||||
|
||||
from ipalib import errors
|
||||
+from ipaplatform.osinfo import osinfo
|
||||
+from ipaplatform.paths import paths
|
||||
+from ipapython.dn import DN
|
||||
+from ipatests.pytest_ipa.integration import tasks
|
||||
+from ipatests.test_integration.base import IntegrationTest
|
||||
+from ipatests.util import xfail_context
|
||||
|
||||
PASSWORD = "DummyPassword123"
|
||||
USER = "opttestuser"
|
||||
@@ -84,6 +85,65 @@ def kinit_otp(host, user, *, password, otp, success=True):
|
||||
)
|
||||
|
||||
|
||||
+def ssh_2fa_with_cmd(host, hostname, username, password, otpvalue,
|
||||
+ command="exit 0"):
|
||||
+ """ ssh to user and in same session pass the command to check tgt of user
|
||||
+ :param host: host to ssh
|
||||
+ :param hostname: hostname to ssh
|
||||
+ :param str username: The name of user
|
||||
+ :param str password: password, usually the first factor
|
||||
+ :param str otpvalue: generated pin of user
|
||||
+ :param str command: command to execute in same session,
|
||||
+ by deafult set to "exit 0"
|
||||
+ :return: object class of expect command run
|
||||
+ """
|
||||
+ temp_conf = tempfile.NamedTemporaryFile(suffix='.exp', delete=False)
|
||||
+ with open(temp_conf.name, 'w') as tfile:
|
||||
+ tfile.write('proc exitmsg { msg code } {\n')
|
||||
+ tfile.write('\t# Close spawned program, if we are in the prompt\n')
|
||||
+ tfile.write('\tcatch close\n\n')
|
||||
+ tfile.write('\t# Wait for the exit code\n')
|
||||
+ tfile.write('\tlassign [wait] pid spawnid os_error_flag rc\n\n')
|
||||
+ tfile.write('\tputs ""\n')
|
||||
+ tfile.write('\tputs "expect result: $msg"\n')
|
||||
+ tfile.write('\tputs "expect exit code: $code"\n')
|
||||
+ tfile.write('\tputs "expect spawn exit code: $rc"\n')
|
||||
+ tfile.write('\texit $code\n')
|
||||
+ tfile.write('}\n')
|
||||
+ tfile.write('set timeout 60\n')
|
||||
+ tfile.write('set prompt ".*\\[#\\$>\\] $"\n')
|
||||
+ tfile.write(f'set password "{password}"\n')
|
||||
+ tfile.write(f'set otpvalue "{otpvalue}"\n')
|
||||
+ tfile.write(f'spawn ssh -o NumberOfPasswordPrompts=1 -o '
|
||||
+ f'StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
|
||||
+ f' -l {username} {hostname} {command}\n')
|
||||
+ tfile.write('expect {\n')
|
||||
+ tfile.write('"Enter first factor:*" {send -- "$password\r"}\n')
|
||||
+ tfile.write('timeout {exitmsg "Unexpected output" 201}\n')
|
||||
+ tfile.write('eof {exitmsg "Unexpected end of file" 202}\n')
|
||||
+ tfile.write('}\n')
|
||||
+ tfile.write('expect {\n')
|
||||
+ tfile.write('"Enter second factor:*" {send -- "$otpvalue\r"}\n')
|
||||
+ tfile.write('timeout {exitmsg "Unexpected output" 201}\n')
|
||||
+ tfile.write('eof {exitmsg "Unexpected end of file" 202}\n')
|
||||
+ tfile.write('}\n')
|
||||
+ tfile.write('expect {\n')
|
||||
+ tfile.write('"Authentication failure" '
|
||||
+ '{exitmsg "Authentication failure" 1}\n')
|
||||
+ tfile.write('eof {exitmsg "Authentication successful" 0}\n')
|
||||
+ tfile.write('timeout {exitmsg "Unexpected output" 201}\n')
|
||||
+ tfile.write('}\n')
|
||||
+ tfile.write('expect {\n')
|
||||
+ tfile.write('exitmsg "Unexpected code path" 203\n')
|
||||
+ tfile.write('EOF\n')
|
||||
+ tfile.write('}')
|
||||
+ host.transport.put_file(temp_conf.name, '/tmp/ssh.exp')
|
||||
+ tasks.clear_sssd_cache(host)
|
||||
+ expect_cmd = 'expect -f /tmp/ssh.exp'
|
||||
+ cmd = host.run_command(expect_cmd, raiseonerr=False)
|
||||
+ return cmd
|
||||
+
|
||||
+
|
||||
def ssh_2f(hostname, username, answers_dict, port=22, unwanted_prompt=""):
|
||||
"""
|
||||
:param hostname: hostname
|
||||
@@ -91,6 +151,7 @@ def ssh_2f(hostname, username, answers_dict, port=22, unwanted_prompt=""):
|
||||
:param answers_dict: dictionary of options with prompt_message and value.
|
||||
:param port: port for ssh
|
||||
"""
|
||||
+
|
||||
# Handler for server questions
|
||||
def answer_handler(title, instructions, prompt_list):
|
||||
resp = []
|
||||
@@ -131,8 +192,9 @@ class TestOTPToken(IntegrationTest):
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
- super(TestOTPToken, cls).install(mh)
|
||||
master = cls.master
|
||||
+ tasks.install_packages(master, ['expect'])
|
||||
+ super(TestOTPToken, cls).install(mh)
|
||||
|
||||
tasks.kinit_admin(master)
|
||||
# create service with OTP auth indicator
|
||||
@@ -398,6 +460,114 @@ class TestOTPToken(IntegrationTest):
|
||||
self.master.run_command(['semanage', 'login', '-D'])
|
||||
sssd_conf_backup.restore()
|
||||
|
||||
+ def test_2fa_only_with_password(self):
|
||||
+ """Test ssh with 2FA only with the password(first factor) when
|
||||
+ user-auth-type is opt and password.
|
||||
+
|
||||
+ Test for : https://github.com/SSSD/sssd/pull/7500
|
||||
+
|
||||
+ Add the IPA user and user-auth-type set to opt and password.
|
||||
+ Authenticate the user only with password, just press enter
|
||||
+ at `Second factor`
|
||||
+ """
|
||||
+ master = self.master
|
||||
+ USER3 = 'sshuser3'
|
||||
+ sssd_conf_backup = tasks.FileBackup(master, paths.SSSD_CONF)
|
||||
+ first_prompt = 'Enter first factor:'
|
||||
+ second_prompt = 'Enter second factor:'
|
||||
+ add_contents = textwrap.dedent('''
|
||||
+ [prompting/2fa/sshd]
|
||||
+ single_prompt = False
|
||||
+ first_prompt = {0}
|
||||
+ second_prompt = {1}
|
||||
+ ''').format(first_prompt, second_prompt)
|
||||
+ set_sssd_conf(master, add_contents)
|
||||
+ tasks.create_active_user(master, USER3, PASSWORD)
|
||||
+ tasks.kinit_admin(master)
|
||||
+ master.run_command(['ipa', 'user-mod', USER3, '--user-auth-type=otp',
|
||||
+ '--user-auth-type=password'])
|
||||
+ try:
|
||||
+ otpuid, totp = add_otptoken(master, USER3, otptype='totp')
|
||||
+ master.run_command(['ipa', 'otptoken-show', otpuid])
|
||||
+ totp.generate(int(time.time())).decode('ascii')
|
||||
+ otpvalue = "\n"
|
||||
+ tasks.clear_sssd_cache(self.master)
|
||||
+ github_ticket = "https://github.com/SSSD/sssd/pull/7500"
|
||||
+ sssd_version = tasks.get_sssd_version(master)
|
||||
+ rhel_fail = (
|
||||
+ osinfo.id == 'rhel'
|
||||
+ and sssd_version < tasks.parse_version("2.9.5")
|
||||
+ )
|
||||
+ fedora_fail = (
|
||||
+ osinfo.id == 'fedora'
|
||||
+ and sssd_version == tasks.parse_version("2.9.5")
|
||||
+ )
|
||||
+ with xfail_context(rhel_fail or fedora_fail, reason=github_ticket):
|
||||
+ result = ssh_2fa_with_cmd(master,
|
||||
+ self.master.external_hostname,
|
||||
+ USER3, PASSWORD, otpvalue=otpvalue,
|
||||
+ command="klist")
|
||||
+ print(result.stdout_text)
|
||||
+ assert ('Authentication successful') in result.stdout_text
|
||||
+ assert USER3 in result.stdout_text
|
||||
+ assert (f'Default principal: '
|
||||
+ f'{USER3}@{self.master.domain.realm}' in
|
||||
+ result.stdout_text)
|
||||
+ cmd = self.master.run_command(['semanage', 'login', '-l'])
|
||||
+ assert USER3 in cmd.stdout_text
|
||||
+ finally:
|
||||
+ master.run_command(['ipa', 'user-del', USER3])
|
||||
+ self.master.run_command(['semanage', 'login', '-D'])
|
||||
+ sssd_conf_backup.restore()
|
||||
+
|
||||
+ def test_2fa_with_otp_password(self):
|
||||
+ """Test ssh with 2FA only with password and otpvalue when
|
||||
+ user-auth-type is opt and password.
|
||||
+
|
||||
+ Test for : https://github.com/SSSD/sssd/pull/7500
|
||||
+
|
||||
+ Add the IPA user and user-auth-type set to opt and password.
|
||||
+ Authenticate the user only with password and otpvalue.
|
||||
+ """
|
||||
+ master = self.master
|
||||
+ USER4 = 'sshuser4'
|
||||
+ sssd_conf_backup = tasks.FileBackup(master, paths.SSSD_CONF)
|
||||
+ first_prompt = 'Enter first factor:'
|
||||
+ second_prompt = 'Enter second factor:'
|
||||
+ add_contents = textwrap.dedent('''
|
||||
+ [prompting/2fa/sshd]
|
||||
+ single_prompt = False
|
||||
+ first_prompt = {0}
|
||||
+ second_prompt = {1}
|
||||
+ ''').format(first_prompt, second_prompt)
|
||||
+ set_sssd_conf(master, add_contents)
|
||||
+ tasks.create_active_user(master, USER4, PASSWORD)
|
||||
+ tasks.kinit_admin(master)
|
||||
+
|
||||
+ master.run_command(['ipa', 'user-mod', USER4, '--user-auth-type=otp',
|
||||
+ '--user-auth-type=password'])
|
||||
+ try:
|
||||
+ otpuid, totp = add_otptoken(master, USER4, otptype='totp')
|
||||
+ master.run_command(['ipa', 'otptoken-show', otpuid])
|
||||
+ otpvalue = totp.generate(int(time.time())).decode('ascii')
|
||||
+ tasks.clear_sssd_cache(self.master)
|
||||
+ result = ssh_2fa_with_cmd(master,
|
||||
+ self.master.external_hostname,
|
||||
+ USER4, PASSWORD, otpvalue=otpvalue,
|
||||
+ command="klist")
|
||||
+ print(result.stdout_text)
|
||||
+ cmd = self.master.run_command(['semanage', 'login', '-l'])
|
||||
+ # check the output
|
||||
+ assert ('Authentication successful') in result.stdout_text
|
||||
+ assert USER4 in result.stdout_text
|
||||
+ assert (f'Default principal: {USER4}@'
|
||||
+ f'{self.master.domain.realm}' in result.stdout_text)
|
||||
+ assert USER4 in cmd.stdout_text
|
||||
+ finally:
|
||||
+ master.run_command(['ipa', 'user-del', USER4])
|
||||
+ self.master.run_command(['semanage', 'login', '-D'])
|
||||
+ sssd_conf_backup.restore()
|
||||
+
|
||||
@pytest.fixture
|
||||
def setup_otp_nsslapd(self):
|
||||
check_services = self.master.run_command(
|
||||
--
|
||||
2.46.2
|
||||
|
36
freeipa.spec
36
freeipa.spec
@ -70,7 +70,7 @@
|
||||
%global krb5_kdb_version 9.0
|
||||
# 0.7.16: https://github.com/drkjam/netaddr/issues/71
|
||||
%global python_netaddr_version 0.7.19
|
||||
%global samba_version 4.20.0-103
|
||||
%global samba_version 4.21.1
|
||||
%global slapi_nis_version 0.56.4
|
||||
%global python_ldap_version 3.1.0-1
|
||||
%if 0%{?rhel} < 9
|
||||
@ -88,7 +88,7 @@
|
||||
%global bind_version 9.11.20-6
|
||||
|
||||
# support for passkey
|
||||
%global sssd_version 2.9.0
|
||||
%global sssd_version 2.9.5
|
||||
|
||||
%else
|
||||
# Fedora
|
||||
@ -224,7 +224,7 @@
|
||||
|
||||
Name: %{package_name}
|
||||
Version: %{IPA_VERSION}
|
||||
Release: 1%{?rc_version:.%rc_version}%{?dist}
|
||||
Release: 2%{?rc_version:.%rc_version}%{?dist}
|
||||
Summary: The Identity, Policy and Audit system
|
||||
|
||||
License: GPL-3.0-or-later
|
||||
@ -250,6 +250,24 @@ Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
|
||||
%if 0%{?rhel} == 9
|
||||
Patch0001: 0001-Revert-Replace-netifaces-with-ifaddr.patch
|
||||
Patch0002: 0002-Revert-custodia-do-not-use-deprecated-jwcrypto-wrapp.patch
|
||||
Patch0003: 0003-ipatests-Check-Default-PAC-type-is-added-to-config.patch
|
||||
Patch0004: 0004-selinux-add-all-IPA-log-files-to-ipa_log_t-file-cont.patch
|
||||
Patch0005: 0005-Add-ipa-idrange-fix.patch
|
||||
Patch0006: 0006-ipatests-Add-missing-comma-in-test_idrange_no_rid_ba.patch
|
||||
Patch0007: 0007-ipatests-Update-ipa-adtrust-install-test.patch
|
||||
Patch0008: 0008-Installer-activate-ssh-service-in-sssd.conf.patch
|
||||
Patch0009: 0009-ipa-migrate-fix-migration-issues-with-entries-using-.patch
|
||||
Patch0010: 0010-ipa-migrate-fix-alternate-entry-search-filter.patch
|
||||
Patch0011: 0011-ipatests-provide-a-ccache-to-rpcclient-deletetrustdo.patch
|
||||
Patch0012: 0012-test_adtrust_install-add-use-krb5-ccache-to-smbclien.patch
|
||||
Patch0013: 0013-Don-t-rely-on-removing-the-CA-to-uninstall-the-ACME-.patch
|
||||
Patch0014: 0014-ipatests-Fixes-for-ipa-idrange-fix-testsuite.patch
|
||||
Patch0015: 0015-Do-not-let-user-with-an-expired-OTP-token-to-log-in-.patch
|
||||
Patch0016: 0016-ipatests-Activate-ssh-in-sssd.conf.patch
|
||||
Patch0017: 0017-ipa-migrate-man-page-fix-typos-and-errors.patch
|
||||
Patch0018: 0018-ipatests-Test-for-ipa-hbac-rule-duplication.patch
|
||||
Patch0019: 0019-ipatests-refactor-password-file-handling-in-TestHSMI.patch
|
||||
Patch0020: 0020-ipatests-2FA-test-cases.patch
|
||||
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
|
||||
%endif
|
||||
%endif
|
||||
@ -1496,6 +1514,7 @@ fi
|
||||
%{_sbindir}/ipa-pkinit-manage
|
||||
%{_sbindir}/ipa-crlgen-manage
|
||||
%{_sbindir}/ipa-cert-fix
|
||||
%{_sbindir}/ipa-idrange-fix
|
||||
%{_sbindir}/ipa-acme-manage
|
||||
%{_sbindir}/ipa-migrate
|
||||
%if 0%{?fedora} >= 38
|
||||
@ -1575,6 +1594,7 @@ fi
|
||||
%{_mandir}/man1/ipa-pkinit-manage.1*
|
||||
%{_mandir}/man1/ipa-crlgen-manage.1*
|
||||
%{_mandir}/man1/ipa-cert-fix.1*
|
||||
%{_mandir}/man1/ipa-idrange-fix.1*
|
||||
%{_mandir}/man1/ipa-acme-manage.1*
|
||||
%{_mandir}/man1/ipa-migrate.1*
|
||||
|
||||
@ -1863,6 +1883,16 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Oct 21 2024 Florence Blanc-Renaud <flo@redhat.com> - 4.12.2-2
|
||||
- Related: RHEL-59788 Rebase Samba to the latest 4.21.x release
|
||||
- Fixes: RHEL-61642 Uninstall ACME separately during PKI uninstallation
|
||||
- Fixes: RHEL-56963 SSSD offline causing test-adtrust-install failure
|
||||
- Fixes: RHEL-56473 Include latest fixes in python3-ipatests packages
|
||||
- Fixes: RHEL-48104 Default hbac rules are duplicated on remote server post ipa-migrate in prod-mode
|
||||
- Fixes: RHEL-45330 [RFE] add a tool to quickly detect and fix issues with IPA ID ranges
|
||||
- Fixes: RHEL-40376 SID generation task is failing when SELinux is in Enforcing mode
|
||||
- Fixes: RHEL-4915 Last expired OTP token would be considered as still assigned to the user
|
||||
|
||||
* Wed Aug 21 2024 Florence Blanc-Renaud <flo@redhat.com> - 4.12.2-1
|
||||
- Resolves: RHEL-54546 Covscan issues: Resource Leak
|
||||
- Resolves: RHEL-49602 misleading warning for missing ipa-selinux-nfast package on luna hsm h/w
|
||||
|
Loading…
Reference in New Issue
Block a user