8e1ca3
From de6f074538f6641fd9d84bed204a3d4d50eccbe5 Mon Sep 17 00:00:00 2001
8e1ca3
From: Rob Crittenden <rcritten@redhat.com>
8e1ca3
Date: Thu, 4 Aug 2022 12:04:41 -0400
8e1ca3
Subject: [PATCH] Set default on group pwpolicy with no grace limit in upgrade
8e1ca3
8e1ca3
If an existing group policy lacks a password grace limit
8e1ca3
update it to -1 on upgrade.
8e1ca3
8e1ca3
Fixes: https://pagure.io/freeipa/issue/9212
8e1ca3
8e1ca3
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
8e1ca3
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
8e1ca3
---
8e1ca3
 .../updates/90-post_upgrade_plugins.update    |  1 +
8e1ca3
 ipaserver/install/plugins/update_pwpolicy.py  | 66 +++++++++++++++++++
8e1ca3
 2 files changed, 67 insertions(+)
8e1ca3
8e1ca3
diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update
8e1ca3
index c7ec71d492b0ac0e7641d586b7e7fa7501743bc2..6fe91aa6c6310a69a7f0feb1ad62243945db67f9 100644
8e1ca3
--- a/install/updates/90-post_upgrade_plugins.update
8e1ca3
+++ b/install/updates/90-post_upgrade_plugins.update
8e1ca3
@@ -26,6 +26,7 @@ plugin: update_ra_cert_store
8e1ca3
 plugin: update_mapping_Guests_to_nobody
8e1ca3
 plugin: fix_kra_people_entry
8e1ca3
 plugin: update_pwpolicy
8e1ca3
+plugin: update_pwpolicy_grace
8e1ca3
 
8e1ca3
 # last
8e1ca3
 # DNS version 1
8e1ca3
diff --git a/ipaserver/install/plugins/update_pwpolicy.py b/ipaserver/install/plugins/update_pwpolicy.py
8e1ca3
index dca44ce4369dfc11f83a412a1249bb045d46713f..4185f034313bd49ca68e86c620043af6ead5f6d6 100644
8e1ca3
--- a/ipaserver/install/plugins/update_pwpolicy.py
8e1ca3
+++ b/ipaserver/install/plugins/update_pwpolicy.py
8e1ca3
@@ -78,3 +78,69 @@ class update_pwpolicy(Updater):
8e1ca3
                 return False, []
8e1ca3
 
8e1ca3
         return False, []
8e1ca3
+
8e1ca3
+
8e1ca3
+@register()
8e1ca3
+class update_pwpolicy_grace(Updater):
8e1ca3
+    """
8e1ca3
+    Ensure all group policies have a grace period set.
8e1ca3
+    """
8e1ca3
+
8e1ca3
+    def execute(self, **options):
8e1ca3
+        ldap = self.api.Backend.ldap2
8e1ca3
+
8e1ca3
+        base_dn = DN(('cn', self.api.env.realm), ('cn', 'kerberos'),
8e1ca3
+                     self.api.env.basedn)
8e1ca3
+        search_filter = (
8e1ca3
+            "(&(objectClass=krbpwdpolicy)(!(passwordgracelimit=*)))"
8e1ca3
+        )
8e1ca3
+
8e1ca3
+        while True:
8e1ca3
+            # Run the search in loop to avoid issues when LDAP limits are hit
8e1ca3
+            # during update
8e1ca3
+
8e1ca3
+            try:
8e1ca3
+                (entries, truncated) = ldap.find_entries(
8e1ca3
+                    search_filter, ['objectclass'], base_dn, time_limit=0,
8e1ca3
+                    size_limit=0)
8e1ca3
+
8e1ca3
+            except errors.EmptyResult:
8e1ca3
+                logger.debug("update_pwpolicy: no policies without "
8e1ca3
+                             "passwordgracelimit set")
8e1ca3
+                return False, []
8e1ca3
+
8e1ca3
+            except errors.ExecutionError as e:
8e1ca3
+                logger.error("update_pwpolicy: cannot retrieve list "
8e1ca3
+                             "of policies missing passwordgracelimit: %s", e)
8e1ca3
+                return False, []
8e1ca3
+
8e1ca3
+            logger.debug("update_pwpolicy: found %d "
8e1ca3
+                         "policies to update, truncated: %s",
8e1ca3
+                         len(entries), truncated)
8e1ca3
+
8e1ca3
+            error = False
8e1ca3
+
8e1ca3
+            for entry in entries:
8e1ca3
+                # Set unlimited BIND by default
8e1ca3
+                entry['passwordgracelimit'] = -1
8e1ca3
+                try:
8e1ca3
+                    ldap.update_entry(entry)
8e1ca3
+                except (errors.EmptyModlist, errors.NotFound):
8e1ca3
+                    pass
8e1ca3
+                except errors.ExecutionError as e:
8e1ca3
+                    logger.debug("update_pwpolicy: cannot "
8e1ca3
+                                 "update policy: %s", e)
8e1ca3
+                    error = True
8e1ca3
+
8e1ca3
+            if error:
8e1ca3
+                # Exit loop to avoid infinite cycles
8e1ca3
+                logger.error("update_pwpolicy: error(s) "
8e1ca3
+                             "detected during pwpolicy update")
8e1ca3
+                return False, []
8e1ca3
+
8e1ca3
+            elif not truncated:
8e1ca3
+                # All affected entries updated, exit the loop
8e1ca3
+                logger.debug("update_pwpolicy: all policies updated")
8e1ca3
+                return False, []
8e1ca3
+
8e1ca3
+        return False, []
8e1ca3
-- 
8e1ca3
2.37.2
8e1ca3