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

On Wednesday, November 17, 2021 at 11:28:44 PM UTC-5 [email protected] wrote:

> 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.
> ---
> - name: KrbPasswordExpiration date/time demo III
>   hosts: localhost
>   vars:
>     cutoff_days: 180
>
>     user_show:
>       json:
>         result:
>           result:
>             krbpasswordexpiration: [
>                 { "__datetime__": "20210107191401Z" },
>               ]
>   tasks:
>     - name: Save expiration date as seconds in the epoch
>       set_fact:
>         exp_epoch: '{{ 
> (user_show.json.result.result.krbpasswordexpiration[0][''__datetime__''] |
>                   to_datetime(''%Y%m%d%H%M%SZ'')).strftime(''%s'') }}'
>     - name: Save the number of days since this password expired
>       set_fact:
>         age: "{{ (ansible_date_time.epoch|int - exp_epoch|int) / ( 60 * 60 
> * 24 ) }}"  # negative values are in the future.
>
>     - name: Disable accounts of users with old passwords.
>       debug:
>         msg: |
>           Cutoff KRB days: {{ cutoff_days }}; age: {{ age }}
>           {% if age|int >= cutoff_days %}
>           !!! Disable account; (pw exp: {{ 
> user_show.json.result.result.krbpasswordexpiration[0]['__datetime__'] }}).
>           {% else %}
>           --- Retain  account; (pw exp: {{ 
> user_show.json.result.result.krbpasswordexpiration[0]['__datetime__'] }}).
>           {% endif %}
>
> and here's the output:
>
> TASK [Save expiration date as seconds in the epoch] 
> ****************************
>
> ok: [localhost] => changed=false 
>   ansible_facts:
>     exp_epoch: '1610064841'
>
> TASK [Save the number of days since this password expired] 
> *********************
>
> ok: [localhost] => changed=false 
>   ansible_facts:
>     age: '314.17319444444445'
>
>
> TASK [Disable accounts of users with old passwords.] 
> ***************************
> ok: [localhost] => 
>   msg: |-
>     Cutoff KRB days: 180; age: 314.17319444444445
>     !!! Disable account; (pw exp: 20210107191401Z).
>
> On Wednesday, November 17, 2021 at 10:13:53 PM UTC-5 Todd Lewis wrote:
>
>> 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.
>>
>> ---
>> - name: KrbPasswordExpiration date/time demo II
>>
>>   hosts: localhost
>>   vars:
>>     user_show:
>>       json:
>>         result:
>>           result:
>>             krbpasswordexpiration: [
>>                 { "__datetime__": "20210107191401Z", "id": "user1" },
>>                 { "__datetime__": "20210213123102Z", "id": "user2" },
>>                 { "__datetime__": "20210327062203Z", "id": "user3" },
>>                 { "__datetime__": "20210411130904Z", "id": "user4" },
>>                 { "__datetime__": "20210519124605Z", "id": "user5" },
>>                 { "__datetime__": "20210604225106Z", "id": "user6" },
>>                 { "__datetime__": "20210711531407Z", "id": "user7" },
>>                 { "__datetime__": "20210818191408Z", "id": "user8" },
>>               ]
>>   tasks:
>>
>>     - name: Save "now - 180 days" in krbpasswordexpiration format
>>       set_fact:
>>         krbpassworddeadline: '{{ lookup(''pipe'',
>>                                         ''date -u --date="now - 180 days" 
>> +%Y%m%d000000Z'') }}'
>>     - name: Disable accounts of users with old passwords.
>>       debug:
>>         msg: |
>>           Cutoff KRB date: {{ krbpassworddeadline }}
>>           {% for item in 
>> user_show.json.result.result.krbpasswordexpiration %}
>>           {%   if krbpassworddeadline > item["__datetime__"] %}
>>           !!! Disable account for "{{ item['id'] }}" (pw exp: {{ 
>> item["__datetime__"] }}).
>>           {%   else %}
>>           --- Retain  account for "{{ item['id'] }}" (pw exp: {{ 
>> item["__datetime__"] }}).
>>           {%   endif %}
>>           {% endfor %}
>>
>> That produces the following output (given that this was run on 
>> 2021-11-17):
>>
>> TASK [Save "now - 180 days" in krbpasswordexpiration format] 
>> *******************
>> ok: [localhost] => changed=false 
>>   ansible_facts:
>>     krbpassworddeadline: 20210522000000Z
>>
>> TASK [Disable accounts of users with old passwords.] 
>> ***************************
>>
>> ok: [localhost] => 
>>   msg: |-
>>     Cutoff KRB date: 20210522000000Z
>>     !!! Disable account for "user1" (pw exp: 20210107191401Z).
>>     !!! Disable account for "user2" (pw exp: 20210213123102Z).
>>     !!! Disable account for "user3" (pw exp: 20210327062203Z).
>>     !!! Disable account for "user4" (pw exp: 20210411130904Z).
>>     !!! Disable account for "user5" (pw exp: 20210519124605Z).
>>     --- Retain  account for "user6" (pw exp: 20210604225106Z).
>>     --- Retain  account for "user7" (pw exp: 20210711531407Z).
>>     --- Retain  account for "user8" (pw exp: 20210818191408Z).
>>
>> On Wednesday, November 17, 2021 at 3:22:26 PM UTC-5 [email protected] 
>> wrote:
>>
>>> 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
>>>
>>>
>>> On Wednesday, November 17, 2021 at 12:10:18 PM UTC-5 [email protected] 
>>> wrote:
>>>
>>>> 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.
>>>>
>>>> On Wednesday, November 17, 2021 at 8:11:28 AM UTC-5 [email protected] 
>>>> wrote:
>>>>
>>>>> 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
>>>>>
>>>>> On Tuesday, November 16, 2021 at 11:15:15 PM UTC-5 [email protected] 
>>>>> wrote:
>>>>>
>>>>>> - 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
>>>>>>
>>>>>> On Tuesday, November 16, 2021 at 12:16:46 PM UTC-5 [email protected] 
>>>>>> wrote:
>>>>>>
>>>>>>> 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
>>>>>>>
>>>>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ansible-project/49c23a4f-e322-453a-a765-9744b7dcd54fn%40googlegroups.com.

Reply via email to