[Freeipa-devel] [PATCH] Resolve SIDs in Web UI

Alexander Bokovoy abokovoy at redhat.com
Fri May 3 18:46:47 UTC 2013


Hi!

Attached are patches to allow resolving SIDs in Web UI in external
membership panel for groups. Please see more detailed description in the
main patch.

I haven't rebased it yet on top of Petr's Web UI rework, hopefully it
should be simple.

https://fedorahosted.org/freeipa/ticket/3302

Since framework doesn't allow to hide commands from CLI, underlying
command is usable from CLI too:
# ipa trust-resolve --sids=S-1-5-21-3502988750-125904550-3683905862-{500,512,498}
  Name: enterprise read-only domain controllers at ad.lan
  SID: S-1-5-21-3502988750-125904550-3683905862-498

  Name: administrator at ad.lan
  SID: S-1-5-21-3502988750-125904550-3683905862-500

  Name: domain admins at ad.lan
  SID: S-1-5-21-3502988750-125904550-3683905862-512

-- 
/ Alexander Bokovoy
-------------- next part --------------
>From a1cffc2ecc0bba739c3b5a5130f939a90dd0b88e Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvoborni at redhat.com>
Date: Wed, 24 Apr 2013 13:48:07 +0200
Subject: [PATCH 2/3] Column promise support

Column setup method can handle promise. It can be supplied directly or encapsulated in a object with temporal value: { promise: promise, temp: 'temp val' }
Temporal value is displayed until promise is fulfilled.
---
 install/ui/src/freeipa/widget.js | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index 17d9b8b..b55900d 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -1388,9 +1388,6 @@ IPA.column = function (spec) {
     }
 
     that.setup = function(container, record, suppress_link) {
-
-        container.empty();
-
         var value = record[that.name];
         var type;
         if (that.formatter) {
@@ -1398,7 +1395,34 @@ IPA.column = function (spec) {
             value = that.formatter.format(value);
             type = that.formatter.type;
         }
+
+        var promise, temp = '';
+        if (value && typeof value.then === 'function') promise = value;
+        if (value && value.promise && typeof value.promise.then === 'function') {
+            promise = value.promise;
+            temp = value.temp || '';
+        }
+
+        if (promise) {
+            var fulfilled = false;
+            promise.then(function(val) {
+                fulfilled = true;
+                that.set_value(container, val, type, suppress_link);
+            });
+
+            if (fulfilled) return;
+            // val obj can contain temporal value which is displayed
+            // until promise is fulfilled
+            value = temp;
+        }
+
+        that.set_value(container, value, type, suppress_link);
+    };
+
+    that.set_value = function(container, value, type, suppress_link) {
+
         value = value ? value.toString() : '';
+        container.empty();
 
         var c;
         if (that.link && !suppress_link) {
-- 
1.8.1.4

-------------- next part --------------
>From 016d3c827f5f9cdecf0d731a993fe5ad92191b59 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Fri, 3 May 2013 21:26:08 +0300
Subject: [PATCH 1/3] web-ui: fix typo in link highliting

---
 install/ui/ipa.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/install/ui/ipa.css b/install/ui/ipa.css
index 3e443d5..8afcfb1 100644
--- a/install/ui/ipa.css
+++ b/install/ui/ipa.css
@@ -779,7 +779,7 @@ div[name=settings].facet-group li a {
     border: none;
 }
 
-.search-table > a:link, a:visted {
+.search-table > a:link, a:visited {
     color:black;
 }
 
-- 
1.8.1.4

-------------- next part --------------
>From 879d686e5cf274446cf345f24be114d23bdc4db9 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Tue, 30 Apr 2013 13:13:25 +0300
Subject: [PATCH 3/3] Resolve SIDs in Web UI

Introduce new command, 'trust-resolve', to aid resolving SIDs to names
in the Web UI.

The command uses new SSSD interface, nss_idmap, to resolve actual SIDs.
SSSD caches resolved data so that future requests to resolve same SIDs
are returned from a memory cache.

Web UI code is using Dojo/Deferred to deliver result of SID resolution
out of band. Once resolved names are available, they replace SID values.

Since Web UI only shows ~20 records per page, up to 20 SIDs are resolved
at the same time. They all sent within the single request to the server.

https://fedorahosted.org/freeipa/ticket/3302
---
 API.txt                               |  7 ++++++
 freeipa.spec.in                       |  4 +++
 install/ui/src/freeipa/association.js | 45 +++++++++++++++++++++++++++++++++-
 install/ui/src/freeipa/entity.js      | 10 +++++++-
 install/ui/src/freeipa/facet.js       | 12 +++++++++
 install/ui/src/freeipa/group.js       |  6 ++---
 ipalib/plugins/trust.py               | 46 +++++++++++++++++++++++++++++++++++
 7 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/API.txt b/API.txt
index c2400e9..e5bb7be 100644
--- a/API.txt
+++ b/API.txt
@@ -3398,6 +3398,13 @@ option: Str('version?', exclude='webui')
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('value', <type 'unicode'>, None)
+command: trust_resolve
+args: 0,4,1
+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('sids+', csv=True)
+option: Str('version?', exclude='webui')
+output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
 command: trust_show
 args: 1,4,3
 arg: Str('cn', attribute=True, cli_name='realm', multivalue=False, primary_key=True, query=True, required=True)
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 36e2a61..1f97418 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -211,6 +211,7 @@ Requires: samba4
 Requires: samba4-winbind
 %endif
 Requires: libsss_idmap
+Requires: libsss_nss_idmap-python
 # We use alternatives to divert winbind_krb5_locator.so plugin to libkrb5
 # on the installes where server-trust-ad subpackage is installed because
 # IPA AD trusts cannot be used at the same time with the locator plugin
@@ -839,6 +840,9 @@ fi
 %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt
 
 %changelog
+* Fri May 03 2013 Alexander Bokovoy <abokovoy at redhat.com> - 3.1.99-10
+- Add libsss_nss_idmap-python dependency for SID resolution
+
 * Tue Apr 30 2013 Rob Crittenden <rcritten at redhat.com> - 3.1.99-9
 - Add Conflicts on nss-pam-ldapd < 0.8.4. The mapping from uniqueMember to
   member is now done automatically and having it in the config file raises
diff --git a/install/ui/src/freeipa/association.js b/install/ui/src/freeipa/association.js
index c6b9e5a..dad138f 100644
--- a/install/ui/src/freeipa/association.js
+++ b/install/ui/src/freeipa/association.js
@@ -22,7 +22,7 @@
 /* CURRENTLY ALSO REQUIRES search.js, because it reuses it's code to create
  * the AssociationList elements; IT NEEDS IT'S OWN CODE! */
 
-define(['./ipa', './jquery', './search', './dialog'], function(IPA, $) {
+define(['dojo/Deferred','./ipa', './jquery', './search', './dialog'], function(Deferred, IPA, $) {
 
 IPA.associator = function (spec) {
 
@@ -1355,6 +1355,49 @@ IPA.attribute_facet = function(spec, no_init) {
     return that;
 };
 
+IPA.sid_facet = function(spec, no_init) {
+
+    spec.name = spec.name || 'sid_facet';
+
+    var that = IPA.attribute_facet(spec, no_init);
+
+    that.load_records = function(value) {
+        var xlate = {}
+        var sidxlate_command = IPA.command({
+            entity: 'trust',
+            method: 'resolve',
+            options: {
+                sids: '',
+            },
+        });
+        sidxlate_command.on_success = function(data, text_status, xhr) {
+            for(var i=0; i< data.result.result.length; i++) {
+                var entry = data.result.result[i]
+                if (entry.sid[0] in xlate) {
+                    xlate[entry.sid[0]].resolve(entry.name[0]);
+                }
+            }
+        };
+        that.table.empty();
+
+        var sids = new Array();
+        for(var i=0; i< value.length; i++) {
+            var sid = value[i][that.attribute];
+            var deferred = new Deferred();
+            deferred.temp = sid;
+            value[i][that.attribute] = deferred;
+            xlate[sid] = deferred;
+            sids.push(sid)
+            that.add_record(value[i]);
+        };
+        sidxlate_command.options.sids = sids;
+        sidxlate_command.execute();
+    };
+
+    return that;
+};
+
+
 IPA.attr_read_only_evaluator = function(spec) {
 
     spec.name = spec.name || 'attr_read_only_evaluator';
diff --git a/install/ui/src/freeipa/entity.js b/install/ui/src/freeipa/entity.js
index 08ba7e5..60fb45e 100644
--- a/install/ui/src/freeipa/entity.js
+++ b/install/ui/src/freeipa/entity.js
@@ -425,6 +425,14 @@ IPA.entity_builder = function() {
         return that;
     };
 
+    that.sid_facet = function(spec) {
+
+        spec.type = spec.type || 'sid';
+
+        that.facet(spec);
+
+        return that;
+    };
     that.standard_association_facets = function(spec) {
 
         spec = spec || {};
@@ -727,4 +735,4 @@ IPA.details_facet_update_policy = function(spec) {
 };
 
 return {};
-});
\ No newline at end of file
+});
diff --git a/install/ui/src/freeipa/facet.js b/install/ui/src/freeipa/facet.js
index 3ad868e..8517507 100644
--- a/install/ui/src/freeipa/facet.js
+++ b/install/ui/src/freeipa/facet.js
@@ -1131,6 +1131,7 @@ IPA.facet_builder = function(entity) {
         that.prepare_methods.details = that.prepare_details_spec;
         that.prepare_methods.association = that.prepare_association_spec;
         that.prepare_methods.attribute = that.prepare_attribute_spec;
+        that.prepare_methods.sid = that.prepare_sid_spec;
     }
 
     that.build_facets = function() {
@@ -1271,6 +1272,17 @@ IPA.facet_builder = function(entity) {
         return false;
     };
 
+    that.prepare_sid_spec = function(spec) {
+        spec.title = spec.title || entity.metadata.label_singular;
+        spec.label = spec.label || entity.metadata.label_singular;
+
+        var attr_metadata = IPA.get_entity_param(entity.name, spec.attribute);
+        spec.tab_label = spec.tab_label || attr_metadata.label;
+        spec.factory = spec.factory || IPA.sid_facet;
+
+        return spec;
+    };
+
     init();
 
     return that;
diff --git a/install/ui/src/freeipa/group.js b/install/ui/src/freeipa/group.js
index a84f49f..dbac380 100644
--- a/install/ui/src/freeipa/group.js
+++ b/install/ui/src/freeipa/group.js
@@ -105,11 +105,11 @@ IPA.group.entity = function(spec) {
             name: 'member_external',
             attribute: 'ipaexternalmember',
             tab_label: 'External',
-            facet_group: 'member',
+            facet_group: 'sid_facet',
             columns: [
                 {
                     name: 'ipaexternalmember',
-                    label: IPA.get_command_option('group_add_member', 'ipaexternalmember').label
+                    label: IPA.get_command_option('group_add_member', 'ipaexternalmember').label,
                 }
             ]
 
@@ -257,4 +257,4 @@ IPA.group.make_external_action = function(spec) {
 IPA.register('group', IPA.group.entity);
 
 return {};
-});
\ No newline at end of file
+});
diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
index a252ad6..fa384c7 100644
--- a/ipalib/plugins/trust.py
+++ b/ipalib/plugins/trust.py
@@ -21,6 +21,7 @@
 from ipalib.plugins.baseldap import *
 from ipalib.plugins.dns import dns_container_exists
 from ipalib import api, Str, StrEnum, Password, DefaultFrom, _, ngettext, Object
+from types import NoneType
 from ipalib.parameters import Enum
 from ipalib import Command
 from ipalib import errors
@@ -32,6 +33,12 @@ try:
 except Exception, e:
     _murmur_installed = False
 
+try:
+    import pysss_nss_idmap #pylint: disable=F0401
+    _nss_idmap_installed = True
+except Exception, e:
+    _nss_idmap_installed = False
+
 if api.env.in_server and api.env.context in ['lite', 'server']:
     try:
         import ipaserver.dcerpc #pylint: disable=F0401
@@ -687,3 +694,42 @@ class trustconfig_show(LDAPRetrieve):
         return dn
 
 api.register(trustconfig_show)
+
+import time
+class trust_resolve(Command):
+    __doc__ = _('Resolve security identifiers of users and groups in trusted domains')
+
+    takes_options = (
+        Str('sids+',
+            label = _('Security Identifiers (SIDs)'),
+            csv = True,
+        ),
+    )
+
+    has_output_params = (
+        Str('name', label= _('Name')),
+        Str('sid', label= _('SID')),
+    )
+
+    has_output = (
+        output.ListOfEntries('result'),
+    )
+
+    def execute(self, *keys, **options):
+        result = list()
+        if not _nss_idmap_installed:
+            return dict(result=result)
+        try:
+            sids = map(lambda x: str(x), options['sids'])
+            xlate = pysss_nss_idmap.getnamebysid(sids)
+            for sid in xlate:
+	       entry = dict()
+               entry['sid'] = [unicode(sid)]
+               entry['name'] = [unicode(xlate[sid])]
+               result.append(entry)
+        except ValueError, e:
+            pass
+
+        return dict(result=result)
+
+api.register(trust_resolve)
-- 
1.8.1.4



More information about the Freeipa-devel mailing list