From 55ec25a75971a854182629cb4027dc9808cd9bb4 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Tue, 16 Jul 2024 15:27:00 +0200
Subject: [PATCH] ipauser: Use date string, not datetime object for expiration
 dates

So far a datetime object was created for the expiration dates
krbpasswordexpiration and krbprincipalexpiration. This resulted in also
sending these objects to the API. With this change, the dates are
converted into strings using the LDAP_GENERALIZED_TIME_FORMAT defined in
ipalib.constants. This way only strings are used with the IPA API.

A new function has been added to ansible_freeipa_module:

- date_string: Convert datetime to gernalized time format string

This fuction is used on the result of user_show to convert the
expiration dates to the gernalized time format string.

The existing function date_format in ansible_freeipa_module has been
renamed to convert_date and fixed in the way that it also uses
date_string to return a gernalized time format string and not a
datetime object. This function was only used in the ipauser module so
far.
---
 plugins/module_utils/ansible_freeipa_module.py | 12 ++++++++++--
 plugins/modules/ipauser.py                     | 16 ++++++++++------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index 9bfad7f6..2f90b3e1 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -353,7 +353,15 @@ def api_check_ipa_version(oper, requested_version):
                      tasks.parse_ipa_version(requested_version))
 
 
-def date_format(value):
+def date_string(value):
+    # Convert datetime to gernalized time format string
+    if not isinstance(value, datetime):
+        raise ValueError("Invalid datetime type '%s'" % repr(value))
+
+    return value.strftime(LDAP_GENERALIZED_TIME_FORMAT)
+
+
+def convert_date(value):
     accepted_date_formats = [
         LDAP_GENERALIZED_TIME_FORMAT,  # generalized time
         '%Y-%m-%dT%H:%M:%SZ',  # ISO 8601, second precision
@@ -365,7 +373,7 @@ def date_format(value):
 
     for _date_format in accepted_date_formats:
         try:
-            return datetime.strptime(value, _date_format)
+            return date_string(datetime.strptime(value, _date_format))
         except ValueError:
             pass
     raise ValueError("Invalid date '%s'" % value)
diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py
index 2ffddc11..d16d2c0c 100644
--- a/plugins/modules/ipauser.py
+++ b/plugins/modules/ipauser.py
@@ -739,10 +739,10 @@ user:
 
 
 from ansible.module_utils.ansible_freeipa_module import \
-    IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \
+    IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, convert_date, \
     encode_certificate, load_cert_from_str, DN_x500_text, to_text, \
     ipalib_errors, gen_add_list, gen_intersection_list, \
-    convert_input_certificates
+    convert_input_certificates, date_string
 from ansible.module_utils import six
 if six.PY3:
     unicode = str
@@ -758,6 +758,10 @@ def find_user(module, name):
     except ipalib_errors.NotFound:
         return None
 
+    # Convert datetime to proper string representation
+    for _expkey in ["krbpasswordexpiration", "krbprincipalexpiration"]:
+        if _expkey in _result:
+            _result[_expkey] = [date_string(x) for x in _result[_expkey]]
     # Transform each principal to a string
     _result["krbprincipalname"] = [
         to_text(x) for x in (_result.get("krbprincipalname") or [])
@@ -1172,12 +1176,12 @@ def main():
     if principalexpiration is not None:
         if principalexpiration[:-1] != "Z":
             principalexpiration = principalexpiration + "Z"
-        principalexpiration = date_format(principalexpiration)
+        principalexpiration = convert_date(principalexpiration)
     passwordexpiration = ansible_module.params_get("passwordexpiration")
     if passwordexpiration is not None:
         if passwordexpiration[:-1] != "Z":
             passwordexpiration = passwordexpiration + "Z"
-        passwordexpiration = date_format(passwordexpiration)
+        passwordexpiration = convert_date(passwordexpiration)
     password = ansible_module.params_get("password")
     random = ansible_module.params_get("random")
     uid = ansible_module.params_get("uid")
@@ -1310,12 +1314,12 @@ def main():
                 if principalexpiration is not None:
                     if principalexpiration[:-1] != "Z":
                         principalexpiration = principalexpiration + "Z"
-                    principalexpiration = date_format(principalexpiration)
+                    principalexpiration = convert_date(principalexpiration)
                 passwordexpiration = user.get("passwordexpiration")
                 if passwordexpiration is not None:
                     if passwordexpiration[:-1] != "Z":
                         passwordexpiration = passwordexpiration + "Z"
-                    passwordexpiration = date_format(passwordexpiration)
+                    passwordexpiration = convert_date(passwordexpiration)
                 password = user.get("password")
                 random = user.get("random")
                 uid = user.get("uid")
-- 
GitLab