mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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
This commit is contained in:
committed by
Petr Viktorin
parent
2775dec3be
commit
91a5d3349b
4
API.txt
4
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')
|
||||
|
2
VERSION
2
VERSION
@@ -89,4 +89,4 @@ IPA_DATA_VERSION=20100614120000
|
||||
# #
|
||||
########################################################
|
||||
IPA_API_VERSION_MAJOR=2
|
||||
IPA_API_VERSION_MINOR=59
|
||||
IPA_API_VERSION_MINOR=60
|
||||
|
@@ -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):
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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 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 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()
|
||||
|
||||
@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,20 +483,14 @@ 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),
|
||||
),
|
||||
),
|
||||
|
||||
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], {}),
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user