mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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
This commit is contained in:
committed by
Martin Kosek
parent
aedded862d
commit
03cdc22c94
7
API.txt
7
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: 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('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
output: Output('value', <type 'unicode'>, 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
|
command: trust_show
|
||||||
args: 1,4,3
|
args: 1,4,3
|
||||||
arg: Str('cn', attribute=True, cli_name='realm', multivalue=False, primary_key=True, query=True, required=True)
|
arg: Str('cn', attribute=True, cli_name='realm', multivalue=False, primary_key=True, query=True, required=True)
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ Requires: samba4
|
|||||||
Requires: samba4-winbind
|
Requires: samba4-winbind
|
||||||
%endif
|
%endif
|
||||||
Requires: libsss_idmap
|
Requires: libsss_idmap
|
||||||
|
Requires: libsss_nss_idmap-python
|
||||||
# We use alternatives to divert winbind_krb5_locator.so plugin to libkrb5
|
# We use alternatives to divert winbind_krb5_locator.so plugin to libkrb5
|
||||||
# on the installes where server-trust-ad subpackage is installed because
|
# 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
|
# IPA AD trusts cannot be used at the same time with the locator plugin
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
* the AssociationList elements; IT NEEDS IT'S OWN CODE! */
|
* the AssociationList elements; IT NEEDS IT'S OWN CODE! */
|
||||||
|
|
||||||
define([
|
define([
|
||||||
|
'dojo/Deferred',
|
||||||
'./ipa',
|
'./ipa',
|
||||||
'./jquery',
|
'./jquery',
|
||||||
'./navigation',
|
'./navigation',
|
||||||
@@ -31,7 +32,7 @@ define([
|
|||||||
'./text',
|
'./text',
|
||||||
'./search',
|
'./search',
|
||||||
'./dialog'],
|
'./dialog'],
|
||||||
function(IPA, $, navigation, phases, reg, text) {
|
function(Deferred, IPA, $, navigation, phases, reg, text) {
|
||||||
|
|
||||||
IPA.associator = function (spec) {
|
IPA.associator = function (spec) {
|
||||||
|
|
||||||
@@ -1364,6 +1365,53 @@ IPA.attribute_facet = function(spec, no_init) {
|
|||||||
return that;
|
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();
|
||||||
|
|
||||||
|
if (value.length === 0) return;
|
||||||
|
|
||||||
|
var sids = [];
|
||||||
|
for (var i=0; i< value.length; i++) {
|
||||||
|
var sid = value[i][that.attribute];
|
||||||
|
var deferred = new Deferred();
|
||||||
|
value[i][that.attribute] = {
|
||||||
|
promise: deferred.promise,
|
||||||
|
temp: sid
|
||||||
|
};
|
||||||
|
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) {
|
IPA.attr_read_only_evaluator = function(spec) {
|
||||||
|
|
||||||
spec.name = spec.name || 'attr_read_only_evaluator';
|
spec.name = spec.name || 'attr_read_only_evaluator';
|
||||||
|
|||||||
@@ -662,4 +662,4 @@ registry.builder.post_ops.push(
|
|||||||
exp.entity_post_ops.deleter_dialog);
|
exp.entity_post_ops.deleter_dialog);
|
||||||
|
|
||||||
return exp;
|
return exp;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
$type: 'attribute',
|
$type: 'attribute',
|
||||||
|
$factory: IPA.sid_facet,
|
||||||
name: 'member_external',
|
name: 'member_external',
|
||||||
attribute: 'ipaexternalmember',
|
attribute: 'ipaexternalmember',
|
||||||
tab_label: 'External',
|
tab_label: 'External',
|
||||||
@@ -280,4 +281,4 @@ exp.register = function() {
|
|||||||
phases.on('registration', exp.register);
|
phases.on('registration', exp.register);
|
||||||
|
|
||||||
return exp;
|
return exp;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1404,9 +1404,6 @@ IPA.column = function (spec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
that.setup = function(container, record, suppress_link) {
|
that.setup = function(container, record, suppress_link) {
|
||||||
|
|
||||||
container.empty();
|
|
||||||
|
|
||||||
var value = record[that.name];
|
var value = record[that.name];
|
||||||
var type;
|
var type;
|
||||||
if (that.formatter) {
|
if (that.formatter) {
|
||||||
@@ -1414,7 +1411,34 @@ IPA.column = function (spec) {
|
|||||||
value = that.formatter.format(value);
|
value = that.formatter.format(value);
|
||||||
type = that.formatter.type;
|
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() : '';
|
value = value ? value.toString() : '';
|
||||||
|
container.empty();
|
||||||
|
|
||||||
var c;
|
var c;
|
||||||
if (that.link && !suppress_link) {
|
if (that.link && !suppress_link) {
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ try:
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
_murmur_installed = False
|
_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']:
|
if api.env.in_server and api.env.context in ['lite', 'server']:
|
||||||
try:
|
try:
|
||||||
import ipaserver.dcerpc #pylint: disable=F0401
|
import ipaserver.dcerpc #pylint: disable=F0401
|
||||||
@@ -687,3 +693,52 @@ class trustconfig_show(LDAPRetrieve):
|
|||||||
return dn
|
return dn
|
||||||
|
|
||||||
api.register(trustconfig_show)
|
api.register(trustconfig_show)
|
||||||
|
|
||||||
|
if _nss_idmap_installed:
|
||||||
|
_idmap_type_dict = {
|
||||||
|
pysss_nss_idmap.ID_USER : 'user',
|
||||||
|
pysss_nss_idmap.ID_GROUP : 'group',
|
||||||
|
pysss_nss_idmap.ID_BOTH : 'both',
|
||||||
|
}
|
||||||
|
def idmap_type_string(level):
|
||||||
|
string = _idmap_type_dict.get(int(level), 'unknown')
|
||||||
|
return unicode(string)
|
||||||
|
|
||||||
|
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][pysss_nss_idmap.NAME_KEY])]
|
||||||
|
entry['type'] = [idmap_type_string(xlate[sid][pysss_nss_idmap.TYPE_KEY])]
|
||||||
|
result.append(entry)
|
||||||
|
except ValueError, e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return dict(result=result)
|
||||||
|
|
||||||
|
api.register(trust_resolve)
|
||||||
|
|||||||
Reference in New Issue
Block a user