# Access expiration date for a user

**URL:** <https://forum.ansible.com/t/access-expiration-date-for-a-user/36000>\
**Category:** Ansible Project\
**Created:** [November 16, 2021, 5:16pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000 "2021-11-16T17:16:46Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [November 16, 2021, 5:16pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/1 "2021-11-16T17:16:46Z")

</div>

I’m using the freeipa APIs in a playbook to get a user’s LDAP information. I can get the krbpasswordexpiration fine:

“krbpasswordexpiration”: [  
{  
“ **datetime** ”: “20220207191401Z”  
}

But I can’t figure out how to access the date string to convert it to a date object. I need it in the form of YYMMDD. If I try to set a fact as follows:

user\_show.json.result.result.krbpasswordexpiration

I get an error about the fact being a list and not a string. How do I pull out the date string so I can turn it into a date?

What I’m ultimately trying to do is grab a user’s expiration date, and compare it to the current date. If the date is greater than or equal to 180, I need to disable the account.

Thanks!  
Harry

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [November 17, 2021, 4:15am UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/2 "2021-11-17T04:15:15Z")

</div>

- name: KrbPasswordExpiration date/time demo  
hosts: localhost  
vars:  
user\_show:  
json:  
result:  
result:  
krbpasswordexpiration: [  
{  
“ **datetime** ”: “20220207191401Z”  
}  
]  
tasks:

- name: Read and manipulate the krb password expiration date/time.  
set\_fact:  
utc: ‘{{ lookup(’‘pipe’‘,  
‘‘date -u --date="’’ +  
(user\_show.json.result.result.krbpasswordexpiration[0][’‘ **datetime** ’‘]|  
regex\_replace(’‘^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z’‘,’‘\1-\2-\3 \4:\5:\6 UTC’‘)) +  
‘’" “+%Y-%m-%d %H:%M:%S %z”’‘) }}’

- name: Do you have the time?  
debug:  
msg:

- “Before: {{ user\_show.json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] }}”

- “After: {{ utc }}”

# \> What I’m ultimately trying to do is grab a user’s expiration date, and compare it to

# \> the current date. If the date is greater than or equal to 180, I need to disable the

# \> account.

# That’s a different problem. Behold:

- name: Save “now - 180 days” in krbpasswordexpiration format  
set\_fact:  
krbpassworddeadline: ‘{{ lookup(’‘pipe’‘,  
‘‘date -u --date=“now - 180 days” +%Y%m%d000000Z’’) }}’

- name: Show the deadline  
debug:  
msg: “krbpassworddeadline: {{ krbpassworddeadline }}”

- name: Expire user  
debug:  
msg:

- “This is where you’d expire the user IFF the following were True:”

- “when: krbpassworddeadline \> user\_show.json.result.result.krbpasswordexpiration[0][‘ **datetime** ’]”

- “i.e. when: {{ krbpassworddeadline }} \> {{ user\_show.json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] }}”

This produces the following output:

TASK [Ansible setup date-time in UTC] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/utoddl/ansible/date-utc2.yml:29  
ok: [localhost] =\> changed=false  
ansible\_facts:  
utc: 2022-02-07 19:14:01 +0000

TASK [Do you have the time?] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/utoddl/ansible/date-utc2.yml:40  
ok: [localhost] =\>  
msg:

- ‘Before: 20220207191401Z’
- ‘After: 2022-02-07 19:14:01 +0000’

TASK [Save “now - 180 days” in krbpasswordexpiration format] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/utoddl/ansible/date-utc2.yml:51  
ok: [localhost] =\> changed=false  
ansible\_facts:  
krbpassworddeadline: 20210521000000Z

TASK [Show the deadline] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/utoddl/ansible/date-utc2.yml:55  
ok: [localhost] =\>  
msg: ‘krbpassworddeadline: 20210521000000Z’

TASK [Expire user] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/utoddl/ansible/date-utc2.yml:59  
ok: [localhost] =\>  
msg:

- ‘This is where you’‘d expire the user IFF the following were True:’
- ‘when: krbpassworddeadline \> user\_show.json.result.result.krbpasswordexpiration[0][’‘ **datetime** ’‘]’
- ‘i.e. when: 20210521000000Z \> 20220207191401Z’  
META: ran handlers  
META: ran handlers

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
localhost : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [November 17, 2021, 1:11pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/3 "2021-11-17T13:11:28Z")

</div>

Thanks for that! I can now reference the **datetime** member, but now I’m trying to convert that to a datetime object in the format of YYmmdd, but I get an error. Here’s how I’m setting the fact now:

- name: Set facts  
set\_fact:  
user\_expires: “{{ user\_show.json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d’) }}”

- name: print results  
debug:  
msg: “{{ user\_expires }} / {{ ansible\_date\_time.year }}{{ ansible\_date\_time.month }}{{ ansible\_date\_time.day }}”

When I run the playbook, it gives me the following error in the set\_fact play:

FAILED! =\> {“msg”: "the field ‘args’ has an invalid value ({u’user\_expires’: u"{{ user\_show.json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d’) }}"}), and could not be converted to an dict.The error was: unconverted data remains: 191401Z\n\n

Any ideas?

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![Dick\_Visser](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Dick\_Visser](https://forum.ansible.com/u/Dick_Visser)\
**Post date:** [November 17, 2021, 4:19pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/4 "2021-11-17T16:19:49Z")

</div>

You need to specify the exact matching format.

Looking at the string at hand (‘20220207191401Z’), try something like:

to\_datetime(‘%Y%m%d%H%M%SZ’)

---

<div class="post-metadata">

**Author:** ![Dick\_Visser](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Dick\_Visser](https://forum.ansible.com/u/Dick_Visser)\
**Post date:** [November 17, 2021, 4:24pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/5 "2021-11-17T16:24:53Z")

</div>

Just some practical tip, if you find yourself needing to isolate things like some jinja/ansible filters, it can be quickly done using ad hoc:

dick.visser@GA0267 ~$ ansible -m debug -i localhost, all -a “msg={{ ‘20220207191401Z’ | to\_datetime(‘%Y%m%d’) }}”  
localhost | FAILED! =\> {  
“msg”: “the field ‘args’ has an invalid value ({‘msg’: "{{ ‘20220207191401Z’ | to\_datetime(‘%Y%m%d’) }}"}), and could not be converted to an dict.The error was: unconverted data remains: 191401Z”  
}

Adjust the pattern:

dick.visser@GA0267 ~$ ansible -m debug -i localhost, all -a “msg={{‘20220207191401Z’|to\_datetime(‘%Y%m%d%H%M%SZ’) }}”  
localhost | SUCCESS =\> {  
“msg”: “2022-02-07 19:14:01”  
}

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [November 17, 2021, 5:10pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/6 "2021-11-17T17:10:18Z")

</div>

You don’t need a datetime object. You just need to know if the string you have sorts before or after this string:

‘{{ lookup(’‘pipe’‘, ‘‘date -u --date=“now - 180 days” +%Y%m%d000000Z’’) }}’  
I would argue “now - 180 days” is going to be a lot easier to understand next year than whatever “pure Ansible” contortions you come up with to do the same thing.

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [November 17, 2021, 8:22pm UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/7 "2021-11-17T20:22:26Z")

</div>

Let me further clarify what I’m looking to do and show where I’m at. We have some bash scripts that check our IPA server user’s and determines their password age. Any user who has not changed their password in 180 days gets automatically disabled. So that expiration date will be in past. In bash we found an “abs” function to make a negative date calculation a positive value. For example, if a person’s account has been expired since May 19, 2021, that is 182 days ago and should be expired. I’m trying to do something similar with Ansible. But I’m working on the date calculations now before expanding.

So I’m able to get the user’s password expiration date using the IPA APIs, and can set the fact for it as assisted above in this thread. I can also get today’s date using the Ansible facts. What I am having an issue with now is trying to use the facts previously calculated to determine the age, and its not working:

- name: Set facts  
set\_fact:  
utc: ‘{{ lookup(’‘pipe’‘,  
‘‘date -u --date="’’ +  
(user\_show.json.result.result.krbpasswordexpiration[0][’‘ **datetime** ’‘]|  
regex\_replace(’‘^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z’‘,’‘\1-\2-\3 \4:\5:\6 UTC’‘)) + ‘’" “+%Y-%m-%d”’‘) }}’  
today: “{{ (ansible\_date\_time.date | to\_datetime(‘%Y-%m-%d’)).date() }}”

age: “{{ ((utc) - (today)).days }}”

FAILED! =\> {“msg”: “Unexpected templating type error occurred on ({{ ((utc) - (today)).days }}): unsupported operand type(s) for -: ‘AnsibleUnsafeText’ and ‘AnsibleUnsafeText’”}

Any ideas on how to reference the “utc” and “today” facts in the “age” fact?

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [November 18, 2021, 3:13am UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/8 "2021-11-18T03:13:53Z")

</div>

Both utc and today are strings (a.k.a. “AnsibleUnsafeText”), so you can’t subtract one from the other. If they were both Python datetime objects, then you could get a difference like that (or something similar).

I’m evidently not communicating clearly, but please know that I have a lot of sympathy for the frustration you’re encountering with data manipulation in Ansible. Been there; got some scorched t-shirts out of it. I see what you’re trying to do, and, while you’re not wrong, and you can make Ansible do it that way, it involves a lot more “code” than is necessary to solve your problem.

I say that because you don’t need “today” or “age”. Nor do you need to manipulate any of the kerberos password “ **datetime** ” values, or convert anything to datetime objects or take their differences. The only new piece of data you need is a string representing the date that was 180 days ago.

Here’s another shot at demonstrating what I’m suggesting.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [November 18, 2021, 4:28am UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/9 "2021-11-18T04:28:44Z")

</div>

If you really want to do it with math (which requires lots of casts to integers) instead of strings, here’s a version that does it that way.

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [November 19, 2021, 1:04am UTC](https://forum.ansible.com/t/access-expiration-date-for-a-user/36000/10 "2021-11-19T01:04:00Z")

</div>

Thanks for that info! It works pretty much how I need it. Now I need to figure out how to loop through all users in our IPA server, get the password expiration, do the calculations, and then disable where needed. The IPA user\_find API method doesn’t return the krbpasswordexpiration. So I may need to do the user find and pull out the user names into a fact, then traverse that using the user\_show IPA API method to get the krbpasswordexpiration value, then go from there. Still planning that part out, but this calculation method is a huge step, and I appreciate everyone’s time and effort to help.

Thanks,  
Harry
