freeipa/ipaserver/plugins/whoami.py
Alexander Bokovoy 381c1c7a8f add whoami command
Whoami command allows to query details about currently
authenticated identity. The command returns following information:

  * object class name
  * function to call to get actual details about the object
  * arguments to pass to the function

There are five types of objects that could bind to IPA using their
credentials. `ipa whoami` call expects one of the following:

  * users
  * staged users
  * hosts
  * Kerberos services
  * ID user override from the default trust view

The latter category of objects is automatically mapped by SASL GSSAPI
mapping rule in 389-ds for users from trusted Active Directory forests.

The command is expected to be used by Web UI to define proper view for
the authenticated identity. It is not visible in the command line
interface is `ipa` command.

Below is an example of how communication looks like for a host
principal:

   # kinit -k
   # ipa console
   (Custom IPA interactive Python console)
   >>> api.Command.whoami()
   {u'command': u'host_show/1', u'object': u'host', u'arguments': (u'ipa.example.com',)}
   >>>

Fixes https://pagure.io/freeipa/issue/6643

Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
2017-03-09 14:10:02 +01:00

137 lines
4.3 KiB
Python

#
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
#
import six
from ipalib import api, Command, errors, output, Str
from ipalib import _
from ipapython.dn import DN
from ipalib.plugable import Registry
from .idviews import DEFAULT_TRUST_VIEW_NAME
if six.PY3:
unicode = str
__doc__ = _("""
Return information about currently authenticated identity
Who am I command returns information on how to get
more details about the identity authenticated for this
request. The information includes:
* type of object
* command to retrieve details of the object
* arguments and options to pass to the command
The information is returned as a dictionary. Examples below use
'key: value' output for illustrative purposes.
EXAMPLES:
Look up as IPA user:
kinit admin
ipa console
>> api.Command.whoami()
------------------------------------------
object: user
command: user_show/1
arguments: admin
------------------------------------------
Look up as a user from a trusted domain:
kinit user@AD.DOMAIN
ipa console
>> api.Command.whoami()
------------------------------------------
object: idoverrideuser
command: idoverrideuser_show/1
arguments: ('default trust view', 'user@ad.domain')
------------------------------------------
Look up as a host:
kinit -k
ipa console
>> api.Command.whoami()
------------------------------------------
object: host
command: host_show/1
arguments: ipa.example.com
------------------------------------------
Look up as a Kerberos service:
kinit -k -t /path/to/keytab HTTP/ipa.example.com
ipa console
>> api.Command.whoami()
------------------------------------------
object: service
command: service_show/1
arguments: HTTP/ipa.example.com
------------------------------------------
""")
register = Registry()
@register()
class whoami(Command):
__doc__ = _('Describe currently authenticated identity.')
NO_CLI = True
output_params = (
Str('object', label=_('Object class name')),
Str('command', label= _('Function to get details')),
Str('arguments*', label=_('Arguments to details function')),
)
has_output = (
output.Output('object', unicode, _('Object class name')),
output.Output('command', unicode, _('Function to get details')),
output.Output('arguments', list, _('Arguments to details function')),
)
def execute(self, **options):
"""
Retrieve the DN we are authenticated as to LDAP and find bindable IPA
object that handles the container where this DN belongs to. Then report
details about this object.
"""
exceptions = {
'idoverrideuser': (DN("cn={0}".format(DEFAULT_TRUST_VIEW_NAME)),
DEFAULT_TRUST_VIEW_NAME, 'ipaOriginalUid'),
}
ldap = api.Backend.ldap2
# whoami_s() call returns a string 'dn: <actual DN value>'
# We also reject ldapi-as-root connections as DM is a virtual object
dn = DN(ldap.conn.whoami_s()[4:])
if dn == DN('cn=Directory Manager'):
raise errors.NotFound(
reason=_('Cannot query Directory Manager with API'))
entry = ldap.get_entry(dn)
o_name = None
o_func = None
o_args = []
for o in api.Object():
if not getattr(o, 'bindable', None):
continue
container = getattr(o, 'container_dn', None)
if container is None:
continue
# Adjust container for exception two-level objects
if o.name in exceptions:
container = exceptions[o.name][0] + container
if dn.find(container + api.env.basedn) == 1:
# We found exact container this DN belongs to
o_name = unicode(o.name)
o_args = [unicode(entry.single_value.get(o.primary_key.name))]
o_func = unicode(o.methods.show.full_name)
if o.name in exceptions:
o_args = [unicode(exceptions[o.name][1]),
unicode(entry.single_value.get(
exceptions[o.name][2]))]
break
return {'object': o_name, 'command': o_func, 'arguments': o_args}