mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 16:10:02 -06:00
Add status command to retrieve user lockout status
This information is not replicated so pull from all IPA masters and display the status across all servers. https://fedorahosted.org/freeipa/ticket/2162
This commit is contained in:
parent
1cc761353b
commit
d5c9f7bcaa
10
API.txt
10
API.txt
@ -3218,6 +3218,16 @@ option: Str('version?', exclude='webui')
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: user_status
|
||||
args: 1,3,4
|
||||
arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', pattern_errmsg='may only include letters, numbers, _, -, . and $', primary_key=True, query=True, required=True)
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||
option: Str('version?', exclude='webui')
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
|
||||
output: Output('count', <type 'int'>, None)
|
||||
output: Output('truncated', <type 'bool'>, None)
|
||||
command: user_unlock
|
||||
args: 1,0,3
|
||||
arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', pattern_errmsg='may only include letters, numbers, _, -, . and $', primary_key=True, query=True, required=True)
|
||||
|
@ -18,7 +18,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from time import gmtime, strftime
|
||||
from time import gmtime, strftime, strptime
|
||||
import copy
|
||||
import string
|
||||
|
||||
@ -27,9 +27,13 @@ from ipalib import Flag, Int, Password, Str, Bool, Bytes
|
||||
from ipalib.plugins.baseldap import *
|
||||
from ipalib.request import context
|
||||
from ipalib import _, ngettext
|
||||
from ipalib import output
|
||||
from ipapython.ipautil import ipa_generate_password
|
||||
import posixpath
|
||||
from ipalib.util import validate_sshpubkey, output_sshpubkey
|
||||
if api.env.in_server and api.env.context in ['lite', 'server']:
|
||||
from ipaserver.plugins.ldap2 import ldap2
|
||||
import os
|
||||
|
||||
__doc__ = _("""
|
||||
Users
|
||||
@ -79,6 +83,21 @@ user_output_params = (
|
||||
),
|
||||
)
|
||||
|
||||
status_output_params = (
|
||||
Str('server',
|
||||
label=_('Server'),
|
||||
),
|
||||
Str('krbloginfailedcount',
|
||||
label=_('Failed logins'),
|
||||
),
|
||||
Str('krblastsuccessfulauth',
|
||||
label=_('Last successful authentication'),
|
||||
),
|
||||
Str('krblastfailedauth',
|
||||
label=_('Last failed authentication'),
|
||||
),
|
||||
)
|
||||
|
||||
# characters to be used for generating random user passwords
|
||||
user_pwdchars = string.digits + string.ascii_letters + '_,.@+-='
|
||||
|
||||
@ -681,3 +700,95 @@ class user_unlock(LDAPQuery):
|
||||
)
|
||||
|
||||
api.register(user_unlock)
|
||||
|
||||
class user_status(LDAPQuery):
|
||||
__doc__ = _("""
|
||||
Lockout status of a user account
|
||||
|
||||
An account may become locked if the password is entered incorrectly too
|
||||
many times within a specific time period as controlled by password
|
||||
policy. A locked account is a temporary condition and may be unlocked by
|
||||
an administrator.
|
||||
|
||||
This connects to each IPA master and displays the lockout status on
|
||||
each one.""")
|
||||
|
||||
has_output = output.standard_list_of_entries
|
||||
has_output_params = LDAPSearch.has_output_params + status_output_params
|
||||
|
||||
def execute(self, *keys, **options):
|
||||
ldap = self.obj.backend
|
||||
dn = self.obj.get_dn(*keys, **options)
|
||||
attr_list = ['krbloginfailedcount', 'krblastsuccessfulauth', 'krblastfailedauth']
|
||||
|
||||
masters = []
|
||||
# Get list of masters
|
||||
try:
|
||||
(masters, truncated) = ldap.find_entries(
|
||||
None, ['*'], 'cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn,
|
||||
ldap.SCOPE_ONELEVEL
|
||||
)
|
||||
except errors.NotFound:
|
||||
# If this happens we have some pretty serious problems
|
||||
self.error('No IPA masters found!')
|
||||
pass
|
||||
|
||||
entries = []
|
||||
count = 0
|
||||
for master in masters:
|
||||
host = master[1]['cn'][0]
|
||||
if host == api.env.host:
|
||||
other_ldap = self.obj.backend
|
||||
else:
|
||||
other_ldap = ldap2(shared_instance=False,
|
||||
ldap_uri='ldap://%s' % host,
|
||||
base_dn=self.api.env.basedn)
|
||||
try:
|
||||
other_ldap.connect(ccache=os.environ['KRB5CCNAME'])
|
||||
except Exception, e:
|
||||
self.error("user_status: Connecting to %s failed with %s" % (host, str(e)))
|
||||
newresult = dict()
|
||||
newresult['dn'] = dn
|
||||
newresult['server'] = _("%(host)s failed: %(error)s") % dict(host=host, error=str(e))
|
||||
entries.append(newresult)
|
||||
count += 1
|
||||
continue
|
||||
try:
|
||||
entry = other_ldap.get_entry(dn, attr_list)
|
||||
newresult = dict()
|
||||
for attr in ['krblastsuccessfulauth', 'krblastfailedauth']:
|
||||
newresult[attr] = entry[1].get(attr, [u'N/A'])
|
||||
newresult['krbloginfailedcount'] = entry[1].get('krbloginfailedcount', u'0')
|
||||
if not options.get('raw', False):
|
||||
for attr in ['krblastsuccessfulauth', 'krblastfailedauth']:
|
||||
try:
|
||||
if newresult[attr][0] == u'N/A':
|
||||
continue
|
||||
newtime = time.strptime(newresult[attr][0], '%Y%m%d%H%M%SZ')
|
||||
newresult[attr][0] = unicode(time.strftime('%Y-%m-%dT%H:%M:%SZ', newtime))
|
||||
except Exception, e:
|
||||
self.debug("time conversion failed with %s" % str(e))
|
||||
pass
|
||||
newresult['dn'] = dn
|
||||
newresult['server'] = host
|
||||
entries.append(newresult)
|
||||
count += 1
|
||||
except errors.NotFound:
|
||||
self.obj.handle_not_found(*keys)
|
||||
except Exception, e:
|
||||
self.error("user_status: Retrieving status for %s failed with %s" % (dn, str(e)))
|
||||
newresult = dict()
|
||||
newresult['dn'] = dn
|
||||
newresult['server'] = _("%(host)s failed") % dict(host=host)
|
||||
entries.append(newresult)
|
||||
count += 1
|
||||
|
||||
if host != api.env.host:
|
||||
other_ldap.destroy_connection()
|
||||
|
||||
return dict(result=entries,
|
||||
count=count,
|
||||
truncated=False,
|
||||
)
|
||||
|
||||
api.register(user_status)
|
||||
|
Loading…
Reference in New Issue
Block a user