summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAna Krivokapic <akrivoka@redhat.com>2013-06-10 18:57:08 -0400
committerPetr Viktorin <pviktori@redhat.com>2013-06-24 14:30:06 +0200
commit91a5d3349be3a8c6044684405a4e66f4ed1dd543 (patch)
treec8d6ee3bbe7eaa81e25ab2b576f6db20345c3090
parent2775dec3bec3499c69de60d5bb581ffad7615cef (diff)
downloadfreeipa-91a5d3349be3a8c6044684405a4e66f4ed1dd543.zip
freeipa-91a5d3349be3a8c6044684405a4e66f4ed1dd543.tar.gz
freeipa-91a5d3349be3a8c6044684405a4e66f4ed1dd543.tar.xz
Require rid-base and secondary-rid-base in idrange-add after ipa-adtrust-install
Add a new API command 'adtrust_is_enabled', which can be used to determine whether ipa-adtrust-install has been run on the system. This new command is not visible in IPA CLI. Use this command in idrange_add to conditionally require rid-base and secondary-rid-base options. Add tests to cover the new functionality https://fedorahosted.org/freeipa/ticket/3634
-rw-r--r--API.txt4
-rw-r--r--VERSION2
-rw-r--r--ipalib/plugins/idrange.py35
-rw-r--r--ipalib/plugins/trust.py32
-rw-r--r--ipatests/test_cmdline/test_cli.py74
-rw-r--r--ipatests/test_xmlrpc/test_range_plugin.py89
-rw-r--r--ipatests/util.py37
7 files changed, 196 insertions, 77 deletions
diff --git a/API.txt b/API.txt
index 1313460..bbffbd4 100644
--- a/API.txt
+++ b/API.txt
@@ -101,6 +101,10 @@ 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: adtrust_is_enabled
+args: 0,1,1
+option: Str('version?', exclude='webui')
+output: Output('result', None, None)
command: automember_add
args: 1,7,3
arg: Str('cn', cli_name='automember_rule')
diff --git a/VERSION b/VERSION
index a95ccb9..c713b18 100644
--- a/VERSION
+++ b/VERSION
@@ -89,4 +89,4 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=59
+IPA_API_VERSION_MINOR=60
diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py
index 54b835e..f258cbb 100644
--- a/ipalib/plugins/idrange.py
+++ b/ipalib/plugins/idrange.py
@@ -356,7 +356,7 @@ class idrange_add(LDAPCreate):
may be given for a new ID range for the local domain while
- --rid-bas
+ --rid-base
--dom-sid
must be given to add a new range for a trusted AD domain.
@@ -381,6 +381,9 @@ class idrange_add(LDAPCreate):
Also ensure that secondary-rid-base is prompted for when rid-base is
specified and vice versa, in case that dom-sid was not specified.
+
+ Also ensure that rid-base and secondary-rid-base is prompted for
+ if ipa-adtrust-install has been run on the system.
"""
# dom-sid can be specified using dom-sid or dom-name options
@@ -410,6 +413,22 @@ class idrange_add(LDAPCreate):
value = self.prompt_param(self.params['ipabaserid'])
kw.update(dict(ipabaserid=value))
+ # Prompt for rid-base and secondary-rid-base if ipa-adtrust-install
+ # has been run on the system
+ adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
+
+ if adtrust_is_enabled:
+ rid_base = kw.get('ipabaserid', None)
+ secondary_rid_base = kw.get('ipasecondarybaserid', None)
+
+ if rid_base is None:
+ value = self.prompt_param(self.params['ipabaserid'])
+ kw.update(dict(ipabaserid=value))
+
+ if secondary_rid_base is None:
+ value = self.prompt_param(self.params['ipasecondarybaserid'])
+ kw.update(dict(ipasecondarybaserid=value))
+
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
@@ -495,6 +514,20 @@ class idrange_add(LDAPCreate):
error=_("Primary RID range and secondary RID range"
" cannot overlap"))
+ # rid-base and secondary-rid-base must be set if
+ # ipa-adtrust-install has been run on the system
+ adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
+
+ if adtrust_is_enabled and not (
+ is_set('ipabaserid') and is_set('ipasecondarybaserid')):
+ raise errors.ValidationError(
+ name='ID Range setup',
+ error=_(
+ 'You must specify both rid-base and '
+ 'secondary-rid-base options, because '
+ 'ipa-adtrust-install has already been run.'
+ )
+ )
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
index 5c9360b..d2b5839 100644
--- a/ipalib/plugins/trust.py
+++ b/ipalib/plugins/trust.py
@@ -20,12 +20,9 @@
from ipalib.plugins.baseldap import *
from ipalib.plugins.dns import dns_container_exists
-from ipalib import api, Str, StrEnum, Password, DefaultFrom, _, ngettext, Object
-from ipalib.parameters import Enum
+from ipalib import api, Str, StrEnum, Password, _, ngettext
from ipalib import Command
from ipalib import errors
-from ipapython import ipautil
-from ipalib import util
try:
import pysss_murmur #pylint: disable=F0401
_murmur_installed = True
@@ -843,3 +840,30 @@ class trust_resolve(Command):
return dict(result=result)
api.register(trust_resolve)
+
+
+class adtrust_is_enabled(Command):
+ NO_CLI = True
+
+ __doc__ = _('Determine whether ipa-adtrust-install has been run on this '
+ 'system')
+
+ def execute(self, *keys, **options):
+ ldap = self.api.Backend.ldap2
+ adtrust_dn = DN(
+ ('cn', 'ADTRUST'),
+ ('cn', api.env.host),
+ ('cn', 'masters'),
+ ('cn', 'ipa'),
+ ('cn', 'etc'),
+ api.env.basedn
+ )
+
+ try:
+ ldap.get_entry(adtrust_dn)
+ except errors.NotFound:
+ return dict(result=False)
+
+ return dict(result=True)
+
+api.register(adtrust_is_enabled)
diff --git a/ipatests/test_cmdline/test_cli.py b/ipatests/test_cmdline/test_cli.py
index fe411b7..fe5ffac 100644
--- a/ipatests/test_cmdline/test_cli.py
+++ b/ipatests/test_cmdline/test_cli.py
@@ -325,3 +325,77 @@ class TestCLIParsing(object):
force=False,
version=API_VERSION
)
+
+ def test_idrange_add(self):
+ """
+ Test idrange-add with interative prompt
+ """
+ def test_with_interactive_input():
+ with self.fake_stdin('5\n500000\n'):
+ self.check_command(
+ 'idrange_add range1 --base-id=1 --range-size=1',
+ 'idrange_add',
+ cn=u'range1',
+ ipabaseid=u'1',
+ ipaidrangesize=u'1',
+ ipabaserid=5,
+ ipasecondarybaserid=500000,
+ all=False,
+ raw=False,
+ version=API_VERSION
+ )
+
+ def test_with_command_line_options():
+ self.check_command(
+ 'idrange_add range1 --base-id=1 --range-size=1 '
+ '--rid-base=5 --secondary-rid-base=500000',
+ 'idrange_add',
+ cn=u'range1',
+ ipabaseid=u'1',
+ ipaidrangesize=u'1',
+ ipabaserid=u'5',
+ ipasecondarybaserid=u'500000',
+ all=False,
+ raw=False,
+ version=API_VERSION
+ )
+
+ def test_without_options():
+ self.check_command(
+ 'idrange_add range1 --base-id=1 --range-size=1',
+ 'idrange_add',
+ cn=u'range1',
+ ipabaseid=u'1',
+ ipaidrangesize=u'1',
+ all=False,
+ raw=False,
+ version=API_VERSION
+ )
+
+ adtrust_dn = 'cn=ADTRUST,cn=%s,cn=masters,cn=ipa,cn=etc,%s' % \
+ (api.env.host, api.env.basedn)
+ adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
+ mockldap = None
+
+ if not adtrust_is_enabled:
+ # ipa-adtrust-install not run - no need to pass rid-base
+ # and secondary-rid-base
+ test_without_options()
+
+ # Create a mock service object to test against
+ adtrust_add = dict(
+ ipaconfigstring='enabledService',
+ objectclass=['top', 'nsContainer', 'ipaConfigObject']
+ )
+
+ mockldap = util.MockLDAP()
+ mockldap.add_entry(adtrust_dn, adtrust_add)
+
+ # Pass rid-base and secondary-rid-base interactively
+ test_with_interactive_input()
+
+ # Pass rid-base and secondary-rid-base on the command-line
+ test_with_command_line_options()
+
+ if not adtrust_is_enabled:
+ mockldap.del_entry(adtrust_dn)
diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py
index 3292d6a..df80e2f 100644
--- a/ipatests/test_xmlrpc/test_range_plugin.py
+++ b/ipatests/test_xmlrpc/test_range_plugin.py
@@ -21,13 +21,11 @@
Test the `ipalib/plugins/idrange.py` module, and XML-RPC in general.
"""
-from ipalib import api, errors, _
-from ipatests.util import assert_equal, Fuzzy
-from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
+from ipalib import api, errors
+from xmlrpc_test import Declarative, fuzzy_uuid
from ipatests.test_xmlrpc import objectclasses
-from ipapython.dn import *
-
-import ldap, ldap.sasl, ldap.modlist
+from ipatests.util import MockLDAP
+from ipapython.dn import DN
id_shift = 0
rid_shift = 0
@@ -99,6 +97,7 @@ testrange8 = u'testrange8'
testrange8_base_id = id_shift + 700
testrange8_size = 50
testrange8_base_rid = rid_shift + 700
+testrange8_secondary_base_rid = rid_shift + 800
testrange9 = u'testrange9'
testrange9_base_id = id_shift + 800
@@ -155,59 +154,23 @@ group1_gid = id_shift + 900100
class test_range(Declarative):
-
- def __init__(self):
- super(test_range, self).__init__()
- self.connection = None
-
- @classmethod
- def connect_ldap(self):
- self.connection = ldap.initialize('ldap://{host}'
- .format(host=api.env.host))
-
- auth = ldap.sasl.gssapi("")
- self.connection.sasl_interactive_bind_s('', auth)
-
- @classmethod
- def add_entry(self, dn, mods):
- ldif = ldap.modlist.addModlist(mods)
- self.connection.add_s(dn, ldif)
-
@classmethod
- def setUpClass(self):
- super(test_range, self).setUpClass()
-
- self.tearDownClass()
-
- try:
- self.connect_ldap()
-
- self.add_entry(testrange9_dn, testrange9_add)
- self.add_entry(testrange10_dn, testrange10_add)
- self.add_entry(testtrust_dn, testtrust_add)
-
- except ldap.ALREADY_EXISTS:
- pass
-
- finally:
- if self.connection is not None:
- self.connection.unbind_s()
+ def setUpClass(cls):
+ super(test_range, cls).setUpClass()
+ cls.tearDownClass()
+ cls.mockldap = MockLDAP()
+ cls.mockldap.add_entry(testrange9_dn, testrange9_add)
+ cls.mockldap.add_entry(testrange10_dn, testrange10_add)
+ cls.mockldap.add_entry(testtrust_dn, testtrust_add)
+ cls.mockldap.unbind()
@classmethod
- def tearDownClass(self):
-
- try:
- self.connect_ldap()
- self.connection.delete_s(testrange9_dn)
- self.connection.delete_s(testrange10_dn)
- self.connection.delete_s(testtrust_dn)
-
- except ldap.NO_SUCH_OBJECT:
- pass
-
- finally:
- if self.connection is not None:
- self.connection.unbind_s()
+ def tearDownClass(cls):
+ cls.mockldap = MockLDAP()
+ cls.mockldap.del_entry(testrange9_dn)
+ cls.mockldap.del_entry(testrange10_dn)
+ cls.mockldap.del_entry(testtrust_dn)
+ cls.mockldap.unbind()
cleanup_commands = [
('idrange_del', [testrange1, testrange2, testrange3, testrange4,
@@ -508,7 +471,9 @@ class test_range(Declarative):
desc='Create ID range %r' % (testrange8),
command=('idrange_add', [testrange8],
dict(ipabaseid=testrange8_base_id,
- ipaidrangesize=testrange8_size)),
+ ipaidrangesize=testrange8_size,
+ ipabaserid=testrange8_base_rid,
+ ipasecondarybaserid=testrange8_secondary_base_rid)),
expected=dict(
result=dict(
dn=DN(('cn',testrange8),('cn','ranges'),('cn','etc'),
@@ -518,6 +483,8 @@ class test_range(Declarative):
ipabaseid=[unicode(testrange8_base_id)],
ipaidrangesize=[unicode(testrange8_size)],
iparangetype=[u'local domain range'],
+ ipabaserid=[unicode(testrange8_base_rid)],
+ ipasecondarybaserid=[unicode(testrange8_secondary_base_rid)]
),
value=testrange8,
summary=u'Added ID range "%s"' % (testrange8),
@@ -525,14 +492,6 @@ class test_range(Declarative):
),
dict(
- desc='Try to modify ID range %r so it has only primary rid range set' % (testrange8),
- command=('idrange_mod', [testrange8],
- dict(ipabaserid=testrange8_base_rid)),
- expected=errors.ValidationError(
- name='ID Range setup', error='Options secondary-rid-base and rid-base must be used together'),
- ),
-
- dict(
desc='Delete ID range %r' % testrange8,
command=('idrange_del', [testrange8], {}),
expected=dict(
diff --git a/ipatests/util.py b/ipatests/util.py
index 117d2c8..30fafdc 100644
--- a/ipatests/util.py
+++ b/ipatests/util.py
@@ -24,6 +24,9 @@ Common utility functions and classes for unit tests.
import inspect
import os
from os import path
+import ldap
+import ldap.sasl
+import ldap.modlist
import tempfile
import shutil
import re
@@ -32,6 +35,7 @@ from ipalib.plugable import Plugin
from ipalib.request import context
from ipapython.dn import DN
+
class TempDir(object):
def __init__(self):
self.__path = tempfile.mkdtemp(prefix='ipa.tests.')
@@ -451,12 +455,6 @@ class ClassChecker(object):
context.__dict__.clear()
-
-
-
-
-
-
def check_TypeError(value, type_, name, callback, *args, **kw):
"""
Tests a standard TypeError raised with `errors.raise_TypeError`.
@@ -635,3 +633,30 @@ class DummyClass(object):
def _calledall(self):
return self.__i == len(self.__calls)
+
+
+class MockLDAP(object):
+ def __init__(self):
+ self.connection = ldap.initialize(
+ 'ldap://{host}'.format(host=ipalib.api.env.host)
+ )
+
+ auth = ldap.sasl.gssapi('')
+ self.connection.sasl_interactive_bind_s('', auth)
+
+ def add_entry(self, dn, mods):
+ try:
+ ldif = ldap.modlist.addModlist(mods)
+ self.connection.add_s(dn, ldif)
+ except ldap.ALREADY_EXISTS:
+ pass
+
+ def del_entry(self, dn):
+ try:
+ self.connection.delete_s(dn)
+ except ldap.NO_SUCH_OBJECT:
+ pass
+
+ def unbind(self):
+ if self.connection is not None:
+ self.connection.unbind_s()