summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2017-03-02 18:03:05 +0200
committerMartin Basti <mbasti@redhat.com>2017-03-09 14:10:02 +0100
commit381c1c7a8fe63526d21cb65decb75fb5ffda676a (patch)
tree30c7356797c1115c18023915ef0ec302f77164d0
parent5cb98496aa2e1e190219cf2f4a6208a38fa368d5 (diff)
downloadfreeipa-381c1c7a8fe63526d21cb65decb75fb5ffda676a.tar.gz
freeipa-381c1c7a8fe63526d21cb65decb75fb5ffda676a.tar.xz
freeipa-381c1c7a8fe63526d21cb65decb75fb5ffda676a.zip
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>
-rw-r--r--API.txt7
-rw-r--r--VERSION.m44
-rw-r--r--ipaserver/plugins/idviews.py5
-rw-r--r--ipaserver/plugins/whoami.py136
4 files changed, 150 insertions, 2 deletions
diff --git a/API.txt b/API.txt
index ace3101dc..90cda748a 100644
--- a/API.txt
+++ b/API.txt
@@ -6451,6 +6451,12 @@ option: Str('version?')
output: Entry('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
+command: whoami/1
+args: 0,1,3
+option: Str('version?')
+output: Output('arguments', type=[<type 'list'>])
+output: Output('command', type=[<type 'unicode'>])
+output: Output('object', type=[<type 'unicode'>])
default: aci/1
default: aci_add/1
default: aci_del/1
@@ -7017,6 +7023,7 @@ default: vaultcontainer_add_owner/1
default: vaultcontainer_del/1
default: vaultcontainer_remove_owner/1
default: vaultcontainer_show/1
+default: whoami/1
capability: messages 2.52
capability: optional_uid_params 2.54
capability: permissions2 2.69
diff --git a/VERSION.m4 b/VERSION.m4
index 8c9327731..f9435664d 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, 219)
-# Last change: Support for Certificate Identity Mapping
+define(IPA_API_VERSION_MINOR, 220)
+# Last change: Add whoami command
########################################################
diff --git a/ipaserver/plugins/idviews.py b/ipaserver/plugins/idviews.py
index 3ee2be4a9..b38a4ad17 100644
--- a/ipaserver/plugins/idviews.py
+++ b/ipaserver/plugins/idviews.py
@@ -818,6 +818,11 @@ class idoverrideuser(baseidoverride):
label_singular = _('User ID override')
rdn_is_primary_key = True
+ # ID user overrides are bindable because we map SASL GSSAPI
+ # authentication of trusted users to ID user overrides in the
+ # default trust view.
+ bindable = True
+
permission_filter_objectclasses = ['ipaUserOverride']
managed_permissions = {
'System: Read User ID Overrides': {
diff --git a/ipaserver/plugins/whoami.py b/ipaserver/plugins/whoami.py
new file mode 100644
index 000000000..0ec6bb8a7
--- /dev/null
+++ b/ipaserver/plugins/whoami.py
@@ -0,0 +1,136 @@
+#
+# 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}