URL: https://github.com/freeipa/freeipa/pull/621
Author: redhatrises
 Title: #621: Add --password-expiration to allow an admin to force a password 
change
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/621/head:pr621
git checkout pr621
From e0f30753a461f3c05401f49a235e18f4610fe426 Mon Sep 17 00:00:00 2001
From: Gabe <redhatri...@gmail.com>
Date: Wed, 29 Mar 2017 20:34:08 -0600
Subject: [PATCH] Add --password-expiration to allow admin to force user
 password expiration

- Allows an admin to easily force a user to expire their password forcing the user to change it immediately or at a specified time in the future
---
 ACI.txt                       |  2 +-
 API.txt                       | 18 ++++++++++++------
 VERSION.m4                    |  4 ++--
 install/updates/20-aci.update |  3 ++-
 ipalib/parameters.py          | 16 ++++++++++------
 ipaserver/plugins/baseuser.py |  4 ++++
 ipaserver/plugins/user.py     |  2 +-
 7 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/ACI.txt b/ACI.txt
index 9c7996c..185812a 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -351,7 +351,7 @@ aci: (targetattr = "member")(target = "ldap:///cn=ipausers,cn=groups,cn=accounts
 dn: cn=users,cn=accounts,dc=ipa,dc=example
 aci: (targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Add Users";allow (add) groupdn = "ldap:///cn=System: Add Users,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=users,cn=accounts,dc=ipa,dc=example
-aci: (targetattr = "krbprincipalkey || passwordhistory || sambalmpassword || sambantpassword || userpassword")(targetfilter = "(&(!(memberOf=cn=admins,cn=groups,cn=accounts,dc=ipa,dc=example))(objectclass=posixaccount))")(version 3.0;acl "permission:System: Change User password";allow (write) groupdn = "ldap:///cn=System: Change User password,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+aci: (targetattr = "krbpasswordexpiration || krbprincipalkey || passwordhistory || sambalmpassword || sambantpassword || userpassword")(targetfilter = "(&(!(memberOf=cn=admins,cn=groups,cn=accounts,dc=ipa,dc=example))(objectclass=posixaccount))")(version 3.0;acl "permission:System: Change User password";allow (write) groupdn = "ldap:///cn=System: Change User password,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=users,cn=accounts,dc=ipa,dc=example
 aci: (targetattr = "ipacertmapdata || objectclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User Certificate Mappings";allow (write) groupdn = "ldap:///cn=System: Manage User Certificate Mappings,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=users,cn=accounts,dc=ipa,dc=example
diff --git a/API.txt b/API.txt
index 7594157..7850538 100644
--- a/API.txt
+++ b/API.txt
@@ -4828,7 +4828,7 @@ output: Entry('result')
 output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
 output: PrimaryKey('value')
 command: stageuser_add/1
-args: 1,44,3
+args: 1,45,3
 arg: Str('uid', cli_name='login')
 option: Str('addattr*', cli_name='addattr')
 option: Flag('all', autofill=True, cli_name='all', default=False)
@@ -4849,6 +4849,7 @@ option: Str('ipasshpubkey*', cli_name='sshpubkey')
 option: Str('ipatokenradiusconfiglink?', cli_name='radius')
 option: Str('ipatokenradiususername?', cli_name='radius_username')
 option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
+option: DateTime('krbpasswordexpiration?', cli_name='password_expiration')
 option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration')
 option: Principal('krbprincipalname*', autofill=True, cli_name='principal')
 option: Str('l?', cli_name='city')
@@ -4933,7 +4934,7 @@ output: Output('result', type=[<type 'dict'>])
 output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
 output: ListOfPrimaryKeys('value')
 command: stageuser_find/1
-args: 1,53,4
+args: 1,54,4
 arg: Str('criteria?')
 option: Flag('all', autofill=True, cli_name='all', default=False)
 option: Str('carlicense*', autofill=False)
@@ -4956,6 +4957,7 @@ option: Str('initials?', autofill=False)
 option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
 option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
 option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
+option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
 option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
 option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
 option: Str('l?', autofill=False, cli_name='city')
@@ -4993,7 +4995,7 @@ output: ListOfEntries('result')
 output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
 output: Output('truncated', type=[<type 'bool'>])
 command: stageuser_mod/1
-args: 1,46,3
+args: 1,47,3
 arg: Str('uid', cli_name='login')
 option: Str('addattr*', cli_name='addattr')
 option: Flag('all', autofill=True, cli_name='all', default=False)
@@ -5014,6 +5016,7 @@ option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
 option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
 option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
 option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
+option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
 option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
 option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
 option: Str('l?', autofill=False, cli_name='city')
@@ -5890,7 +5893,7 @@ output: Entry('result')
 output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
 output: PrimaryKey('value')
 command: user_add/1
-args: 1,45,3
+args: 1,46,3
 arg: Str('uid', cli_name='login')
 option: Str('addattr*', cli_name='addattr')
 option: Flag('all', autofill=True, cli_name='all', default=False)
@@ -5910,6 +5913,7 @@ option: Str('ipasshpubkey*', cli_name='sshpubkey')
 option: Str('ipatokenradiusconfiglink?', cli_name='radius')
 option: Str('ipatokenradiususername?', cli_name='radius_username')
 option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
+option: DateTime('krbpasswordexpiration?', cli_name='password_expiration')
 option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration')
 option: Principal('krbprincipalname*', autofill=True, cli_name='principal')
 option: Str('l?', cli_name='city')
@@ -6011,7 +6015,7 @@ output: Output('result', type=[<type 'bool'>])
 output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
 output: PrimaryKey('value')
 command: user_find/1
-args: 1,56,4
+args: 1,57,4
 arg: Str('criteria?')
 option: Flag('all', autofill=True, cli_name='all', default=False)
 option: Str('carlicense*', autofill=False)
@@ -6034,6 +6038,7 @@ option: Str('initials?', autofill=False)
 option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
 option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
 option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
+option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
 option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
 option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
 option: Str('l?', autofill=False, cli_name='city')
@@ -6074,7 +6079,7 @@ output: ListOfEntries('result')
 output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
 output: Output('truncated', type=[<type 'bool'>])
 command: user_mod/1
-args: 1,47,3
+args: 1,48,3
 arg: Str('uid', cli_name='login')
 option: Str('addattr*', cli_name='addattr')
 option: Flag('all', autofill=True, cli_name='all', default=False)
@@ -6095,6 +6100,7 @@ option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
 option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
 option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
 option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
+option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
 option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
 option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
 option: Str('l?', autofill=False, cli_name='city')
diff --git a/VERSION.m4 b/VERSION.m4
index 4b11d48..6ec56c5 100644
--- a/VERSION.m4
+++ b/VERSION.m4
@@ -73,8 +73,8 @@ define(IPA_DATA_VERSION, 20100614120000)
 #                                                      #
 ########################################################
 define(IPA_API_VERSION_MAJOR, 2)
-define(IPA_API_VERSION_MINOR, 224)
-# Last change: Add rename option to sudorule objects
+define(IPA_API_VERSION_MINOR, 225)
+# Last change: Add --password-expiration option to force password change
 
 
 ########################################################
diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update
index a15f9fe..10ce25c 100644
--- a/install/updates/20-aci.update
+++ b/install/updates/20-aci.update
@@ -54,7 +54,8 @@ remove:aci:(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword ||
 add:aci:(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbPasswordExpiration || krbPwdHistory || krbLastPwdChange || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || ipaUniqueId || memberOf || enrolledBy || ipaNTHash || ipaProtectedOperation")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
 # Write-only
 remove:aci:(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
-add:aci:(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || ipaNTHash")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
+remove:aci:(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || ipaNTHash")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
+add:aci:(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || ipaNTHash || krbPasswordExpiration")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
 add:aci:(targetfilter = "(objectClass=krbPwdPolicy)")(targetattr = "krbMaxPwdLife || krbMinPwdLife || krbPwdMinDiffChars || krbPwdMinLength || krbPwdHistoryLength")(version 3.0;acl "Admins can write password policies"; allow (read, search, compare, write) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
 # Read-only
 add:aci:(targetattr="ipaUniqueId || memberOf || enrolledBy || krbExtraData || krbPrincipalName || krbCanonicalName || krbPasswordExpiration || krbLastPwdChange || krbLastSuccessfulAuth || krbLastFailedAuth")(version 3.0; acl "Admin read-only attributes"; allow (read, search, compare) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";;)
diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 7fbe63e..107cc90 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -1665,12 +1665,16 @@ class DateTime(Param):
 
     def _convert_scalar(self, value, index=None):
         if isinstance(value, six.string_types):
-            for date_format in self.accepted_formats:
-                try:
-                    time = datetime.datetime.strptime(value, date_format)
-                    return time
-                except ValueError:
-                    pass
+            if value == u'now':
+                time = datetime.datetime.utcnow()
+                return time
+            else:
+                for date_format in self.accepted_formats:
+                    try:
+                        time = datetime.datetime.strptime(value, date_format)
+                        return time
+                    except ValueError:
+                        pass
 
             # If we get here, the strptime call did not succeed for any
             # the accepted formats, therefore raise error
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
index bf24dbf..8fbec73 100644
--- a/ipaserver/plugins/baseuser.py
+++ b/ipaserver/plugins/baseuser.py
@@ -239,6 +239,10 @@ class baseuser(LDAPObject):
             cli_name='principal_expiration',
             label=_('Kerberos principal expiration'),
         ),
+        DateTime('krbpasswordexpiration?',
+            cli_name='password_expiration',
+            label=_('User password expiration'),
+        ),
         Str('mail*',
             cli_name='email',
             label=_('Email address'),
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
index 2d29dfb..9eab521 100644
--- a/ipaserver/plugins/user.py
+++ b/ipaserver/plugins/user.py
@@ -261,7 +261,7 @@ class user(baseuser):
             ],
             'ipapermdefaultattr': {
                 'krbprincipalkey', 'passwordhistory', 'sambalmpassword',
-                'sambantpassword', 'userpassword'
+                'sambantpassword', 'userpassword', 'krbpasswordexpiration'
             },
             'replaces': [
                 '(target = "ldap:///uid=*,cn=users,cn=accounts,$SUFFIX";)(targetattr = "userpassword || krbprincipalkey || sambalmpassword || sambantpassword || passwordhistory")(version 3.0;acl "permission:Change a user password";allow (write) groupdn = "ldap:///cn=Change a user password,cn=permissions,cn=pbac,$SUFFIX";)',
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to