summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/trust.py
diff options
context:
space:
mode:
authorTomas Babej <tbabej@redhat.com>2013-07-17 15:55:36 +0200
committerAlexander Bokovoy <abokovoy@redhat.com>2013-07-23 16:24:33 +0300
commit17c7d46c254de8301a1c328155d245631d5c03e4 (patch)
tree03bf7d5b8c970f6d353c5a082eb992dc969c7c9d /ipalib/plugins/trust.py
parent84b2269589c115cae2d2bcec32fec602143fc42e (diff)
downloadfreeipa-17c7d46c254de8301a1c328155d245631d5c03e4.tar.gz
freeipa-17c7d46c254de8301a1c328155d245631d5c03e4.tar.xz
freeipa-17c7d46c254de8301a1c328155d245631d5c03e4.zip
Use AD LDAP probing to create trusted domain ID range
When creating a trusted domain ID range, probe AD DC to get information about ID space leveraged by POSIX users already defined in AD, and create an ID range with according parameters. For more details: http://www.freeipa.org/page/V3/Use_posix_attributes_defined_in_AD https://fedorahosted.org/freeipa/ticket/3649
Diffstat (limited to 'ipalib/plugins/trust.py')
-rw-r--r--ipalib/plugins/trust.py111
1 files changed, 99 insertions, 12 deletions
diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
index 965ff76bb..b19a27eca 100644
--- a/ipalib/plugins/trust.py
+++ b/ipalib/plugins/trust.py
@@ -20,9 +20,13 @@
from ipalib.plugins.baseldap import *
from ipalib.plugins.dns import dns_container_exists
+from ipapython.ipautil import realm_to_suffix
from ipalib import api, Str, StrEnum, Password, _, ngettext
from ipalib import Command
from ipalib import errors
+from ldap import SCOPE_SUBTREE
+from time import sleep
+
try:
import pysss_murmur #pylint: disable=F0401
_murmur_installed = True
@@ -292,8 +296,6 @@ sides.
Int('range_size?',
cli_name='range_size',
label=_('Size of the ID range reserved for the trusted domain'),
- default=DEFAULT_RANGE_SIZE,
- autofill=True
),
StrEnum('range_type?',
label=_('Range type'),
@@ -313,7 +315,7 @@ sides.
result = self.execute_ad(full_join, *keys, **options)
if not old_range:
- self.add_range(range_name, dom_sid, **options)
+ self.add_range(range_name, dom_sid, *keys, **options)
trust_filter = "cn=%s" % result['value']
ldap = self.obj.backend
@@ -418,9 +420,7 @@ sides.
'Only the ipa-ad-trust and ipa-ad-trust-posix are '
'allowed values for --range-type when adding an AD '
'trust.'
- )
-
-)
+ ))
base_id = options.get('base_id')
range_size = options.get('range_size') != DEFAULT_RANGE_SIZE
@@ -468,9 +468,96 @@ sides.
return old_range, range_name, dom_sid
- def add_range(self, range_name, dom_sid, **options):
- base_id = options.get('base_id')
- if not base_id:
+ def add_range(self, range_name, dom_sid, *keys, **options):
+ """
+ First, we try to derive the parameters of the ID range based on the
+ information contained in the Active Directory.
+
+ If that was not successful, we go for our usual defaults (random base,
+ range size 200 000, ipa-ad-trust range type).
+
+ Any of these can be overriden by passing appropriate CLI options
+ to the trust-add command.
+ """
+
+ range_size = None
+ range_type = None
+ base_id = None
+
+ # First, get information about ID space from AD
+ # However, we skip this step if other than ipa-ad-trust-posix
+ # range type is enforced
+
+ if options.get('range_type', None) in (None, u'ipa-ad-trust-posix'):
+
+ # Get the base dn
+ domain = keys[-1]
+ basedn = realm_to_suffix(domain)
+
+ # Search for information contained in
+ # CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System
+ info_filter = '(objectClass=msSFU30DomainInfo)'
+ info_dn = DN('CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System')\
+ + basedn
+
+ # Get the domain validator
+ domain_validator = ipaserver.dcerpc.DomainValidator(self.api)
+ if not domain_validator.is_configured():
+ raise errors.NotFound(
+ reason=_('Cannot search in trusted domains without own '
+ 'domain configured. Make sure you have run '
+ 'ipa-adtrust-install on the IPA server first'))
+
+ # KDC might not get refreshed data at the first time,
+ # retry several times
+ for retry in range(10):
+ info_list = domain_validator.search_in_dc(domain,
+ info_filter,
+ None,
+ SCOPE_SUBTREE,
+ basedn=info_dn,
+ use_http=True,
+ quiet=True)
+
+ if info_list:
+ info = info_list[0]
+ break
+ else:
+ sleep(2)
+
+ required_msSFU_attrs = ['msSFU30MaxUidNumber', 'msSFU30OrderNumber']
+
+ if not info_list:
+ # We were unable to gain UNIX specific info from the AD
+ self.log.debug("Unable to gain POSIX info from the AD")
+ else:
+ if all(attr in info for attr in required_msSFU_attrs):
+ self.log.debug("Able to gain POSIX info from the AD")
+ range_type = u'ipa-ad-trust-posix'
+
+ max_uid = info.get('msSFU30MaxUidNumber')
+ max_gid = info.get('msSFU30MaxGidNumber', None)
+ max_id = int(max(max_uid, max_gid)[0])
+
+ base_id = int(info.get('msSFU30OrderNumber')[0])
+ range_size = (1 + (max_id - base_id) / DEFAULT_RANGE_SIZE)\
+ * DEFAULT_RANGE_SIZE
+
+ # Second, options given via the CLI options take precedence to discovery
+ if options.get('range_type', None):
+ range_type = options.get('range_type', None)
+ elif not range_type:
+ range_type = u'ipa-ad-trust'
+
+ if options.get('range_size', None):
+ range_size = options.get('range_size', None)
+ elif not range_size:
+ range_size = DEFAULT_RANGE_SIZE
+
+ if options.get('base_id', None):
+ base_id = options.get('base_id', None)
+ elif not base_id:
+ # Generate random base_id if not discovered nor given via CLI
base_id = DEFAULT_RANGE_SIZE + (
pysss_murmur.murmurhash3(
dom_sid,
@@ -478,12 +565,12 @@ sides.
) % 10000
) * DEFAULT_RANGE_SIZE
- # Add new ID range
+ # Finally, add new ID range
api.Command['idrange_add'](range_name,
ipabaseid=base_id,
- ipaidrangesize=options['range_size'],
+ ipaidrangesize=range_size,
ipabaserid=0,
- iparangetype=options.get('range_type'),
+ iparangetype=range_type,
ipanttrusteddomainsid=dom_sid)
def execute_ad(self, full_join, *keys, **options):