dirsrvtests/tests/suites/filter/rfc3673_all_oper_attrs_test.py | 209 ++++++++++
dirsrvtests/tests/tickets/ticket48363_test.py | 206 ---------
2 files changed, 209 insertions(+), 206 deletions(-)
New commits:
commit 03c1e860a58c07b6c24767178aa3048ea7771c30
Author: Simon Pichugin <spichugi(a)redhat.com>
Date: Fri May 20 10:54:51 2016 +0200
Ticket 48363 - CI test - add test suite
Description: Refactor and improve test suite for the requesting
all attributes with '+' feature.
Please see:
https://tools.ietf.org/html/rfc3673
https://fedorahosted.org/389/ticket/48363
Review by: wibrown (Thanks!)
diff --git a/dirsrvtests/tests/suites/filter/rfc3673_all_oper_attrs_test.py
b/dirsrvtests/tests/suites/filter/rfc3673_all_oper_attrs_test.py
new file mode 100644
index 0000000..efea5a5
--- /dev/null
+++ b/dirsrvtests/tests/suites/filter/rfc3673_all_oper_attrs_test.py
@@ -0,0 +1,209 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+
+import os
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+DN_PEOPLE = 'ou=people,%s' % DEFAULT_SUFFIX
+DN_ROOT = ''
+TEST_USER_NAME = 'all_attrs_test'
+TEST_USER_DN = 'uid=%s,%s' % (TEST_USER_NAME, DN_PEOPLE)
+TEST_USER_PWD = 'all_attrs_test'
+
+# Suffix for search, Regular user boolean, List of expected attrs
+TEST_PARAMS = [(DN_ROOT, False, [
+ 'aci', 'createTimestamp', 'creatorsName',
+ 'modifiersName', 'modifyTimestamp',
'namingContexts',
+ 'nsBackendSuffix', 'nsUniqueId',
'subschemaSubentry',
+ 'supportedControl', 'supportedExtension',
+ 'supportedFeatures', 'supportedLDAPVersion',
+ 'supportedSASLMechanisms', 'vendorName',
'vendorVersion'
+ ]),
+ (DN_ROOT, True, [
+ 'createTimestamp', 'creatorsName',
+ 'modifiersName', 'modifyTimestamp',
'namingContexts',
+ 'nsBackendSuffix', 'nsUniqueId',
'subschemaSubentry',
+ 'supportedControl', 'supportedExtension',
+ 'supportedFeatures', 'supportedLDAPVersion',
+ 'supportedSASLMechanisms', 'vendorName',
'vendorVersion'
+ ]),
+ (DN_PEOPLE, False, [
+ 'aci', 'createTimestamp', 'creatorsName',
'entrydn',
+ 'entryid', 'modifiersName',
'modifyTimestamp',
+ 'nsUniqueId', 'numSubordinates', 'parentid'
+ ]),
+ (DN_PEOPLE, True, [
+ 'aci', 'createTimestamp', 'creatorsName',
'entrydn',
+ 'entryid', 'modifyTimestamp', 'nsUniqueId',
+ 'numSubordinates', 'parentid'
+ ]),
+ (TEST_USER_DN, False, [
+ 'createTimestamp', 'creatorsName', 'entrydn',
+ 'entryid', 'modifiersName',
'modifyTimestamp',
+ 'nsUniqueId', 'parentid'
+ ]),
+ (TEST_USER_DN, True, [
+ 'createTimestamp', 'creatorsName', 'entrydn',
+ 'entryid', 'modifyTimestamp', 'nsUniqueId',
'parentid'
+ ]),
+ (DN_CONFIG, False, ['numSubordinates',
'passwordHistory'])]
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ # Creating standalone instance ...
+ standalone = DirSrv(verbose=False)
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ standalone.delete()
+ standalone.create()
+ standalone.open()
+
+ # Delete each instance in the end
+ def fin():
+ standalone.delete()
+ request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ standalone.clearTmpDir(__file__)
+
+ return TopologyStandalone(standalone)
+
+
+(a)pytest.fixture(scope="module")
+def test_user(topology):
+ """User for binding operation"""
+
+ try:
+ topology.standalone.add_s(Entry((TEST_USER_DN, {
+ 'objectclass': 'top
person'.split(),
+ 'objectclass':
'organizationalPerson',
+ 'objectclass': 'inetorgperson',
+ 'cn': TEST_USER_NAME,
+ 'sn': TEST_USER_NAME,
+ 'userpassword': TEST_USER_PWD,
+ 'mail': '%s(a)redhat.com' %
TEST_USER_NAME,
+ 'uid': TEST_USER_NAME
+ })))
+ except ldap.LDAPError as e:
+ log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN,
+ e.message['desc']))
+ raise e
+
+
+(a)pytest.fixture(scope="module")
+def user_aci(topology):
+ """Deny modifiersName attribute for the test user
+ under whole suffix
+ """
+
+ ACI_TARGET = '(targetattr= "modifiersName")'
+ ACI_ALLOW = '(version 3.0; acl "Deny modifiersName for user"; deny
(read)'
+ ACI_SUBJECT = ' userdn = "ldap:///%s";)' % TEST_USER_DN
+ ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD,
+ 'aci',
+ ACI_BODY)])
+
+
+def test_supported_features(topology):
+ """Verify that OID 1.3.6.1.4.1.4203.1.5.1 is published
+ in the supportedFeatures [RFC3674] attribute in the rootDSE.
+
+ :Feature: Filter
+
+ :Setup: Standalone instance
+
+ :Steps: 1. Search for 'supportedFeatures' at rootDSE
+
+ :Assert: Value 1.3.6.1.4.1.4203.1.5.1 is presented
+ """
+
+ entries = topology.standalone.search_s('', ldap.SCOPE_BASE,
+ '(objectClass=*)',
+ ['supportedFeatures'])
+ supported_value = entries[0].data['supportedfeatures']
+
+ assert supported_value == ['1.3.6.1.4.1.4203.1.5.1']
+
+
+(a)pytest.mark.parametrize('add_attr', ['', '*',
'objectClass'])
+(a)pytest.mark.parametrize('search_suffix,regular_user,oper_attr_list',
+ TEST_PARAMS)
+def test_search_basic(topology, test_user, user_aci, add_attr,
+ search_suffix, regular_user, oper_attr_list):
+ """Verify that you can get all expected operational attributes
+ by a Search Request [RFC2251] with '+' (ASCII 43) filter.
+ Please see:
https://tools.ietf.org/html/rfc3673
+
+ :Feature: Filter
+
+ :Setup: Standalone instance, test user for binding,
+ deny one attribute aci for that user
+
+ :Steps: 1. Bind as regular user or Directory Manager
+ 2. Search with '+' filter and with additionaly
+ 'objectClass' and '*' attrs too
+
+ :Assert: All expected values were returned, not more
+ """
+
+ if regular_user:
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
+ else:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ search_filter = ['+']
+ if add_attr:
+ search_filter.append(add_attr)
+ expected_attrs = sorted(oper_attr_list + ['objectClass'])
+ else:
+ expected_attrs = sorted(oper_attr_list)
+
+ entries = topology.standalone.search_s(search_suffix, ldap.SCOPE_BASE,
+ '(objectclass=*)',
+ search_filter)
+ found_attrs = sorted(entries[0].data.keys())
+
+ if add_attr == '*':
+ # Check that found attrs contain both operational
+ # and non-operational attributes
+ assert all(attr in found_attrs
+ for attr in ['objectClass', expected_attrs[0]])
+ else:
+ assert cmp(found_attrs, expected_attrs) == 0
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/tickets/ticket48363_test.py
b/dirsrvtests/tests/tickets/ticket48363_test.py
deleted file mode 100644
index 33245a1..0000000
--- a/dirsrvtests/tests/tickets/ticket48363_test.py
+++ /dev/null
@@ -1,206 +0,0 @@
-import os
-import sys
-import time
-import ldap
-import logging
-import pytest
-from lib389 import DirSrv, Entry, tools, tasks
-from lib389.tools import DirSrvTools
-from lib389._constants import *
-from lib389.properties import *
-from lib389.tasks import *
-from lib389.utils import *
-
-logging.getLogger(__name__).setLevel(logging.DEBUG)
-log = logging.getLogger(__name__)
-
-TEST_USER = 'uid=test,%s' % DEFAULT_SUFFIX
-# Well, it's better than "password" or "password1"
-TEST_PASS = 'banana cream pie'
-
-class TopologyStandalone(object):
- def __init__(self, standalone):
- standalone.open()
- self.standalone = standalone
-
-
-(a)pytest.fixture(scope="module")
-def topology(request):
-
- # Creating standalone instance ...
- standalone = DirSrv(verbose=False)
- args_instance[SER_HOST] = HOST_STANDALONE
- args_instance[SER_PORT] = PORT_STANDALONE
- args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
- args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
- args_standalone = args_instance.copy()
- standalone.allocate(args_standalone)
- instance_standalone = standalone.exists()
- if instance_standalone:
- standalone.delete()
- standalone.create()
- standalone.open()
-
- # Delete each instance in the end
- def fin():
- standalone.delete()
- request.addfinalizer(fin)
-
- # Clear out the tmp dir
- standalone.clearTmpDir(__file__)
-
- return TopologyStandalone(standalone)
-
-
-def test_ticket48363(topology):
- """
- Test the implementation of rfc3673, '+' for all operational attributes.
-
- Please see:
https://tools.ietf.org/html/rfc3673
-
- """
-
- # Test the implementation of the supportFeatures
-
- # Section 2:
- # Servers supporting this feature SHOULD publish the Object Identifier
- # 1.3.6.1.4.1.4203.1.5.1 as a value of the 'supportedFeatures'
- # [RFC3674] attribute in the root DSE.
-
- results = topology.standalone.search_s('', ldap.SCOPE_BASE,
'objectClass=*', ['supportedFeatures'] )[0]
- if results.hasAttr('supportedfeatures') is False:
- assert False
- if results.hasValue('supportedfeatures', '1.3.6.1.4.1.4203.1.5.1') is
False:
- assert False
-
- # Section 2:
- # The presence of the attribute description "+" (ASCII 43) in the list
- # of attributes in a Search Request [RFC2251] SHALL signify a request
- # for the return of all operational attributes.
-
- # Test the two backends, rootdse, and a real ldbm backend
-
- # Root DSE
- results = topology.standalone.search_s('', ldap.SCOPE_BASE,
'objectClass=*', ['+'] )[0]
- # There are a number of obvious ones in rootdse. These are:
-
- rootdse_op_attrs = [
- 'supportedExtension',
- 'supportedControl',
- 'supportedFeatures',
- 'supportedSASLMechanisms',
- 'supportedLDAPVersion',
- 'vendorName',
- 'vendorVersion',
- ]
-
- for opattr in rootdse_op_attrs:
- if results.hasAttr(opattr) is False:
- assert False
-
- # LDBM backend
- # We are going to examine the root of the suffix, as it's a good easy target
- dc_op_attrs = [
- 'nsuniqueid',
- 'entrydn',
- 'entryid',
- 'aci',
- ]
- dc_user_attrs = [
- 'objectClass',
- 'dc',
- ]
-
- # We should show that the following work:
-
- # '+'
- results = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_BASE,
'objectClass=*', ['+'] )[0]
- for opattr in dc_op_attrs:
- if results.hasAttr(opattr) is False:
- assert False
- for userattr in dc_user_attrs:
- if results.hasAttr(userattr) is False:
- assert True
-
- # '+' '*'
- results = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_BASE,
'objectClass=*', ['+', '*'] )[0]
- for opattr in dc_op_attrs:
- if results.hasAttr(opattr) is False:
- assert False
- for userattr in dc_user_attrs:
- if results.hasAttr(userattr) is False:
- assert False
-
- # Section 2:
- # Client implementors should also note
- # that certain operational attributes may be returned only if requested
- # by name even when "+" is present.
-
- # We do not currently have any types that are excluded.
- # However, we should ensure that a search for "+ namedType" returns
- # both all operational and the namedType
-
- # '+' dc
- results = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_BASE,
'objectClass=*', ['+', 'dc'] )[0]
- for opattr in dc_op_attrs:
- if results.hasAttr(opattr) is False:
- assert False
- if results.hasAttr('dc') is False:
- assert False
- if results.hasAttr('objectclass') is False:
- assert True
-
- # '*' nsUniqueId
- results = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_BASE,
'objectClass=*', ['*', 'nsuniqueid'] )[0]
- for userattr in dc_user_attrs:
- if results.hasAttr(userattr) is False:
- assert False
- if results.hasAttr('nsuniqueid') is False:
- assert False
- if results.hasAttr('entrydn') is False:
- assert True
-
- # Section 2:
- # As with all search requests, client implementors should note that
- # results may not include all requested attributes due to access
- # controls or other restrictions.
-
- # Test that with a user with limit read aci, that these are enforced on
- # the + request.
-
- # Create the user
- uentry = Entry(TEST_USER)
- uentry.setValues('objectclass', 'top', 'extensibleobject')
- uentry.setValues('uid', 'test')
- uentry.setValues('userPassword', TEST_PASS)
- topology.standalone.add_s(uentry)
-
- # Give them a limited read aci: We may need to purge other acis
- anonaci = '(targetattr!="userPassword")(version 3.0; acl "Enable
anonymous access"; allow (read, search, compare)
userdn="ldap:///anyone";)'
- topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_DELETE, 'aci',
anonaci)])
-
- # Now we need to create an aci that allows anon/all read to only a few attrs
- # Lets make one real, and one operational.
-
- anonaci = '(targetattr="objectclass || dc || nsuniqueid")(version 3.0;
acl "Enable anonymous access"; allow (read, search, compare)
userdn="ldap:///anyone";)'
- topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci',
anonaci)])
-
- # bind as them, and test.
- topology.standalone.simple_bind_s(TEST_USER, TEST_PASS)
- results = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_BASE,
'objectClass=*', ['*', '+'] )[0]
-
- if results.hasAttr('dc') is False:
- assert False
- if results.hasAttr('nsuniqueid') is False:
- assert False
- if results.hasAttr('entrydn') is False:
- assert True
-
- log.info('Test complete')
-
-
-if __name__ == '__main__':
- # Run isolated
- # -s for DEBUG mode
- CURRENT_FILE = os.path.realpath(__file__)
- pytest.main("-s %s" % CURRENT_FILE)