Add option to specify SID using domain name to idrange-add/mod

When adding/modifying an ID range for a trusted domain, the newly
added option --dom-name can be used. This looks up SID of the
trusted domain in LDAP and therefore the user is not required
to write it down in CLI. If the lookup fails, error message
asking the user to specify the SID manually is shown.

https://fedorahosted.org/freeipa/ticket/3133
This commit is contained in:
Tomas Babej 2013-02-04 08:33:53 -05:00 committed by Martin Kosek
parent 3f8778890e
commit 559a87017a
3 changed files with 95 additions and 15 deletions

View File

@ -1885,13 +1885,14 @@ command: i18n_messages
args: 0,0,1
output: Output('messages', <type 'dict'>, None)
command: idrange_add
args: 1,11,3
args: 1,12,3
arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
option: Str('addattr*', cli_name='addattr', exclude='webui')
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Int('ipabaseid', attribute=True, cli_name='base_id', multivalue=False, required=True)
option: Int('ipabaserid', attribute=True, cli_name='rid_base', multivalue=False, required=False)
option: Int('ipaidrangesize', attribute=True, cli_name='range_size', multivalue=False, required=True)
option: Str('ipanttrusteddomainname', attribute=False, cli_name='dom_name', multivalue=False, required=False)
option: Str('ipanttrusteddomainsid', attribute=True, cli_name='dom_sid', multivalue=False, required=False)
option: Str('iparangetype', attribute=True, cli_name='iparangetype', multivalue=False, required=False)
option: Int('ipasecondarybaserid', attribute=True, cli_name='secondary_rid_base', multivalue=False, required=False)
@ -1929,7 +1930,7 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('truncated', <type 'bool'>, None)
command: idrange_mod
args: 1,13,3
args: 1,14,3
arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
option: Str('addattr*', cli_name='addattr', exclude='webui')
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@ -1937,6 +1938,7 @@ option: Str('delattr*', cli_name='delattr', exclude='webui')
option: Int('ipabaseid', attribute=True, autofill=False, cli_name='base_id', multivalue=False, required=False)
option: Int('ipabaserid', attribute=True, autofill=False, cli_name='rid_base', multivalue=False, required=False)
option: Int('ipaidrangesize', attribute=True, autofill=False, cli_name='range_size', multivalue=False, required=False)
option: Str('ipanttrusteddomainname', attribute=False, autofill=False, cli_name='dom_name', multivalue=False, required=False)
option: Str('ipanttrusteddomainsid', attribute=True, autofill=False, cli_name='dom_sid', multivalue=False, required=False)
option: Str('iparangetype', attribute=True, autofill=False, cli_name='iparangetype', multivalue=False, required=False)
option: Int('ipasecondarybaserid', attribute=True, autofill=False, cli_name='secondary_rid_base', multivalue=False, required=False)

View File

@ -57,7 +57,7 @@ Additionally an ID range of the local domain may set
and an ID range of a trusted domain must set
- rid-base: the first RID of the corresponding RID range
- dom_sid: domain SID of the trusted domain
- sid: domain SID of the trusted domain
@ -197,6 +197,11 @@ class idrange(LDAPObject):
cli_name='dom_sid',
label=_('Domain SID of the trusted domain'),
),
Str('ipanttrusteddomainname?',
cli_name='dom_name',
flags=('no_search', 'virtual_attribute'),
label=_('Name of the trusted domain'),
),
Str('iparangetype?',
label=_('Range type'),
flags=['no_option'],
@ -265,17 +270,42 @@ class idrange(LDAPObject):
error=_('range modification leaving objects with ID out '
'of the defined range is not allowed'))
def validate_trusted_domain_sid(self, sid):
def get_domain_validator(self):
if not _dcerpc_bindings_installed:
raise errors.NotFound(reason=_('Cannot perform SID validation without Samba 4 support installed. '
'Make sure you have installed server-trust-ad sub-package of IPA on the server'))
raise errors.NotFound(reason=_('Cannot perform SID validation '
'without Samba 4 support installed. Make sure you have '
'installed server-trust-ad sub-package of IPA on the server'))
domain_validator = ipaserver.dcerpc.DomainValidator(self.api)
if not domain_validator.is_configured():
raise errors.NotFound(reason=_('Cross-realm trusts are not configured. '
'Make sure you have run ipa-adtrust-install on the IPA server first'))
raise errors.NotFound(reason=_('Cross-realm trusts are not '
'configured. Make sure you have run ipa-adtrust-install '
'on the IPA server first'))
return domain_validator
def validate_trusted_domain_sid(self, sid):
domain_validator = self.get_domain_validator()
if not domain_validator.is_trusted_sid_valid(sid):
raise errors.ValidationError(name='domain SID',
error=_('SID is not recognized as a valid SID for a trusted domain'))
error=_('SID is not recognized as a valid SID for a '
'trusted domain'))
def get_trusted_domain_sid_from_name(self, name):
""" Returns unicode string representation for given trusted domain name
or None if SID forthe given trusted domain name could not be found."""
domain_validator = self.get_domain_validator()
sid = domain_validator.get_sid_from_domain_name(name)
if sid is not None:
sid = unicode(sid)
return sid
# checks that primary and secondary rid ranges do not overlap
def are_rid_ranges_overlapping(self, rid_base, secondary_rid_base, size):
@ -336,26 +366,45 @@ class idrange_add(LDAPCreate):
is_set = lambda x: (x in entry_attrs) and (x is not None)
# This needs to stay in options since there is no
# ipanttrusteddomainname attribute in LDAP
if 'ipanttrusteddomainname' in options:
if is_set('ipanttrusteddomainsid'):
raise errors.ValidationError(name='ID Range setup',
error=_('Options dom-sid and dom-name '
'cannot be used together'))
sid = self.obj.get_trusted_domain_sid_from_name(
options['ipanttrusteddomainname'])
if sid is not None:
entry_attrs['ipanttrusteddomainsid'] = sid
else:
raise errors.ValidationError(name='ID Range setup',
error=_('SID for the specified trusted domain name could '
'not be found. Please specify the SID directly '
'using dom-sid option.'))
if is_set('ipanttrusteddomainsid'):
if is_set('ipasecondarybaserid'):
raise errors.ValidationError(name='ID Range setup',
error=_('Options dom_sid and secondary_rid_base cannot '
'be used together'))
error=_('Options dom-sid/dom-name and secondary-rid-base '
'cannot be used together'))
if not is_set('ipabaserid'):
raise errors.ValidationError(name='ID Range setup',
error=_('Options dom_sid and rid_base must '
error=_('Options dom-sid/dom-name and rid-base must '
'be used together'))
# Validate SID as the one of trusted domains
self.obj.validate_trusted_domain_sid(options['ipanttrusteddomainsid'])
self.obj.validate_trusted_domain_sid(entry_attrs['ipanttrusteddomainsid'])
# Finally, add trusted AD domain range object class
entry_attrs['objectclass'].append('ipatrustedaddomainrange')
else:
if is_set('ipasecondarybaserid') != is_set('ipabaserid'):
raise errors.ValidationError(name='ID Range setup',
error=_('Options secondary_rid_base and rid_base must '
error=_('Options secondary-rid-base and rid-base must '
'be used together'))
if is_set('ipabaserid') and is_set('ipasecondarybaserid'):
@ -436,6 +485,25 @@ class idrange_mod(LDAPUpdate):
is_set = lambda x: (x in entry_attrs) and (x is not None)
# This needs to stay in options since there is no
# ipanttrusteddomainname attribute in LDAP
if 'ipanttrusteddomainname' in options:
if is_set('ipanttrusteddomainsid'):
raise errors.ValidationError(name='ID Range setup',
error=_('Options dom-sid and dom-name '
'cannot be used together'))
sid = self.obj.get_trusted_domain_sid_from_name(
options['ipanttrusteddomainname'])
if sid is not None:
entry_attrs['ipanttrusteddomainsid'] = sid
else:
raise errors.ValidationError(name='ID Range setup',
error=_('SID for the specified trusted domain name could '
'not be found. Please specify the SID directly '
'using dom-sid option.'))
try:
(old_dn, old_attrs) = ldap.get_entry(dn,
['ipabaseid',
@ -447,7 +515,7 @@ class idrange_mod(LDAPUpdate):
if is_set('ipanttrusteddomainsid'):
# Validate SID as the one of trusted domains
self.obj.validate_trusted_domain_sid(options['ipanttrusteddomainsid'])
self.obj.validate_trusted_domain_sid(entry_attrs['ipanttrusteddomainsid'])
# ensure that primary and secondary rid ranges do not overlap
if all((base in entry_attrs) or (base in old_attrs)

View File

@ -204,6 +204,16 @@ class DomainValidator(object):
else:
return True
def get_sid_from_domain_name(self, name):
"""Returns binary representation of SID for the trusted domain name
or None if name is not in the list of trusted domains."""
domains = self.get_trusted_domains()
if name in domains:
return domains[name][1]
else:
return None
def get_trusted_domain_objects(self, domain=None, flatname=None, filter="",
attrs=None, scope=_ldap.SCOPE_SUBTREE, basedn=None):
"""