Example #1
0
def test_user(topology_st, request):
    """User for binding operation"""

    log.info('Adding user {}'.format(BN))
    try:
        topology_st.standalone.add_s(
            Entry((BN, {
                'objectclass':
                ['top', 'person', 'organizationalPerson', 'inetOrgPerson'],
                'cn':
                'bind user',
                'sn':
                'bind user',
                'userPassword':
                PASSWORD
            })))
        log.info('Adding an aci for the bind user')
        BN_ACI = '(targetattr="*")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///%s";)' % BN
        ous = OrganisationalUnits(topology_st.standalone, DEFAULT_SUFFIX)
        ou_people = ous.get('people')
        ou_people.add('aci', BN_ACI)
    except ldap.LDAPError as e:
        log.error('Failed to add user (%s): error (%s)' %
                  (BN, e.message['desc']))
        raise e

    def fin():
        log.info('Deleting user {}'.format(BN))
        topology_st.standalone.delete_s(BN)
        ous = OrganisationalUnits(topology_st.standalone, DEFAULT_SUFFIX)
        ou_people = ous.get('people')
        ou_people.remove('aci', BN_ACI)

    request.addfinalizer(fin)
def entries(topology_m2, request):
    """Adds entries to the master1"""

    master1 = topology_m2.ms["master1"]

    test_list = []

    log.info("Add 100 nested entries under replicated suffix on %s" %
             master1.serverid)
    ous = OrganisationalUnits(master1, DEFAULT_SUFFIX)
    for i in range(100):
        ou = ous.create(properties={
            'ou': 'test_ou_%s' % i,
        })
        test_list.append(ou)

    log.info("Delete created entries")
    for test_ou in test_list:
        test_ou.delete()

    def fin():
        log.info("Clear the errors log in the end of the test case")
        with open(master1.errlog, 'w') as errlog:
            errlog.writelines("")

    request.addfinalizer(fin)
Example #3
0
def password_policy(topology_st, test_user):
    """Set global password policy.
    Then, set fine-grained subtree level password policy
    to ou=People with no password syntax.

    Note: do not touch nsslapd-pwpolicy-inherit-global -- off by default
    """

    log.info('Enable fine-grained policy')
    try:
        topology_st.standalone.config.set('nsslapd-pwpolicy-local', 'on')
    except ldap.LDAPError as e:
        log.error('Failed to set fine-grained policy: error {}'.format(
            e.message['desc']))
        raise e

    log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
    try:
        subprocess.call([
            '%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(),
            '-D', DN_DM, '-w', PASSWORD, '-p',
            str(PORT_STANDALONE), '-h', HOST_STANDALONE, '-S', OU_PEOPLE, '-Z',
            SERVERID_STANDALONE
        ])
    except subprocess.CalledProcessError as e:
        log.error('Failed to create pw policy policy for {}: error {}'.format(
            OU_PEOPLE, e.message['desc']))
        raise e

    log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
    try:
        ous = OrganisationalUnits(topology_st.standalone, DEFAULT_SUFFIX)
        ou_people = ous.get('people')
        ou_people.set('pwdpolicysubentry', PWP_CONTAINER_PEOPLE)
    except ldap.LDAPError as e:
        log.error('Failed to pwdpolicysubentry pw policy ' \
                  'policy for {}: error {}'.format(OU_PEOPLE,
                                                   e.message['desc']))
        raise e

    log.info("Set the default settings for the policy container.")
    topology_st.standalone.modify_s(
        PWP_CONTAINER_PEOPLE,
        [(ldap.MOD_REPLACE, 'passwordMustChange', b'off'),
         (ldap.MOD_REPLACE, 'passwordExp', b'off'),
         (ldap.MOD_REPLACE, 'passwordMinAge', b'0'),
         (ldap.MOD_REPLACE, 'passwordChange', b'off'),
         (ldap.MOD_REPLACE, 'passwordStorageScheme', b'ssha')])

    check_attr_val(topology_st, CONFIG_DN, ATTR_INHERIT_GLOBAL, 'off')
    check_attr_val(topology_st, CONFIG_DN, ATTR_CHECK_SYNTAX, 'off')
def test_services(topology):
    """
    Test and assert that a simple service account can be bound to and created.

    These are really useful in simple tests.
    """
    ous = OrganisationalUnits(topology.standalone, DEFAULT_SUFFIX)
    services = ServiceAccounts(topology.standalone, DEFAULT_SUFFIX)

    # Create the OU for them.
    ous.create(
        properties={
            'ou': 'Services',
            'description': 'Computer Service accounts which request DS bind',
        })
    # Now, we can create the services from here.
    service = services.create(properties={
        'cn': 'testbind',
        'userPassword': '******'
    })

    conn = service.bind('Password1')
    conn.unbind_s()
Example #5
0
def test_indirect_template_scale(topology_st):
    """Test that cos templates can be added at a reasonable scale

    :id: 7cbcdf22-1f9c-4222-9e76-685fe374fc20
    :steps:
        1. Enable COS plugin
        2. Create the test user
        3. Add an indirect cos template
        4. Add a cos template
        5. Add the user to the cos template and assert it works.
        6. Add 25,000 templates to the database
        7. Search the user. It should not exceed THRESHOLD.
    :expected results:
        1. It is enabled.
        2. It is created.
        3. Is is created.
        4. It is created.
        5. It is valid.
        6. They are created.
        7. It is fast.
    """

    cos_plugin = ClassOfServicePlugin(topology_st.standalone)
    cos_plugin.enable()

    topology_st.standalone.restart()

    # Now create, the indirect specifier, and a user to template onto.
    users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
    user = users.create(properties=TEST_USER_PROPERTIES)

    cos_inds = CosIndirectDefinitions(topology_st.standalone, DEFAULT_SUFFIX)
    cos_ind = cos_inds.create(properties={
        'cn' : 'cosIndirectDef',
        'cosIndirectSpecifier': 'seeAlso',
        'cosAttribute': [
            'ou merge-schemes',
            'description merge-schemes',
            'postalCode merge-schemes',
            ],
    })

    ous = OrganisationalUnits(topology_st.standalone, DEFAULT_SUFFIX)
    ou_temp = ous.create(properties={'ou': 'templates'})
    cos_temps = OUCosTemplates(topology_st.standalone, ou_temp.dn)

    cos_temp_u = cos_temps.create(properties={
        'ou' : 'ou_temp_u',
        'description' : 'desc_temp_u',
        'postalCode': '0'
    })
    # Edit the user to add the seeAlso ...
    user.set('seeAlso', cos_temp_u.dn)

    # Now create 25,0000 templates, they *don't* need to apply to the user though!
    for i in range(1, 25001):
        cos_temp_u = cos_temps.create(properties={
            'ou' : 'ou_temp_%s' % i,
            'description' : 'desc_temp_%s' % i,
            'postalCode': '%s' % i
        })

        if i % 500 == 0:
            start_time = time.monotonic()
            u_search = users.get('testuser')
            attrs = u_search.get_attr_vals_utf8('postalCode')
            end_time = time.monotonic()
            diff_time = end_time - start_time
            assert diff_time < THRESHOLD

        if i == 10000:
            # Now add our user to this template also.
            user.add('seeAlso', cos_temp_u.dn)

            start_time = time.monotonic()
            attrs_after = u_search.get_attr_vals_utf8('postalCode')
            end_time = time.monotonic()
            diff_time = end_time - start_time
            assert(set(attrs) < set(attrs_after))
            assert diff_time < THRESHOLD
    def _apply(self):
        # Create the base domain object
        domain = Domain(self._instance, dn=self._basedn)
        # Explode the dn to get the first bit.
        avas = dn.str2dn(self._basedn)
        dc_ava = avas[0][0][1]

        domain.create(properties={
            # I think in python 2 this forces unicode return ...
            'dc': dc_ava,
            'description': self._basedn,
            'aci': [
                # Allow reading the base domain object
                '(targetattr="dc || description || objectClass")(targetfilter="(objectClass=domain)")(version 3.0; acl "Enable anyone domain read"; allow (read, search, compare)(userdn="ldap:///anyone");)',
                # Allow reading the ou
                '(targetattr="ou || objectClass")(targetfilter="(objectClass=organizationalUnit)")(version 3.0; acl "Enable anyone ou read"; allow (read, search, compare)(userdn="ldap:///anyone");)'
            ]
            })

        # Create the 389 service container
        # This could also move to be part of core later ....
        hidden_containers = nsHiddenContainers(self._instance, self._basedn)
        ns389container = hidden_containers.create(properties={
            'cn': '389_ds_system'
            })

        # Create our ous.
        ous = OrganisationalUnits(self._instance, self._basedn)
        ous.create(properties = {
            'ou': 'groups',
            'aci': [
                # Allow anon partial read
                '(targetattr="cn || member || gidNumber || nsUniqueId || description || objectClass")(targetfilter="(objectClass=groupOfNames)")(version 3.0; acl "Enable anyone group read"; allow (read, search, compare)(userdn="ldap:///anyone");)',
                # Allow group_modify to modify but not create groups
                '(targetattr="member")(targetfilter="(objectClass=groupOfNames)")(version 3.0; acl "Enable group_modify to alter members"; allow (write)(groupdn="ldap:///cn=group_modify,ou=permissions,{BASEDN}");)'.format(BASEDN=self._basedn),
                # Allow group_admin to fully manage groups (posix or not).
                '(targetattr="cn || member || gidNumber || description || objectClass")(targetfilter="(objectClass=groupOfNames)")(version 3.0; acl "Enable group_admin to manage groups"; allow (write, add, delete)(groupdn="ldap:///cn=group_admin,ou=permissions,{BASEDN}");)'.format(BASEDN=self._basedn),
            ]
        })

        ous.create(properties = {
            'ou': 'people',
            'aci': [
                # allow anon partial read.
                '(targetattr="objectClass || description || nsUniqueId || uid || displayName || loginShell || uidNumber || gidNumber || gecos || homeDirectory || cn || memberOf || mail || nsSshPublicKey || nsAccountLock || userCertificate")(targetfilter="(objectClass=posixaccount)")(version 3.0; acl "Enable anyone user read"; allow (read, search, compare)(userdn="ldap:///anyone");)',
                # allow self partial mod
                '(targetattr="displayName || nsSshPublicKey")(version 3.0; acl "Enable self partial modify"; allow (write)(userdn="ldap:///self");)',
                # Allow self full read
                '(targetattr="legalName || telephoneNumber || mobile")(targetfilter="(objectClass=nsPerson)")(version 3.0; acl "Enable self legalname read"; allow (read, search, compare)(userdn="ldap:///self");)',
                # Allow reading legal name
                '(targetattr="legalName || telephoneNumber")(targetfilter="(objectClass=nsPerson)")(version 3.0; acl "Enable user legalname read"; allow (read, search, compare)(groupdn="ldap:///cn=user_private_read,ou=permissions,{BASEDN}");)'.format(BASEDN=self._basedn),
                # These below need READ so they can read userPassword and legalName
                # Allow user admin create mod
                '(targetattr="uid || description || displayName || loginShell || uidNumber || gidNumber || gecos || homeDirectory || cn || memberOf || mail || legalName || telephoneNumber || mobile")(targetfilter="(&(objectClass=nsPerson)(objectClass=nsAccount))")(version 3.0; acl "Enable user admin create"; allow (write, add, delete, read)(groupdn="ldap:///cn=user_admin,ou=permissions,{BASEDN}");)'.format(BASEDN=self._basedn),
                # Allow user mod mod only
                '(targetattr="uid || description || displayName || loginShell || uidNumber || gidNumber || gecos || homeDirectory || cn || memberOf || mail || legalName || telephoneNumber || mobile")(targetfilter="(&(objectClass=nsPerson)(objectClass=nsAccount))")(version 3.0; acl "Enable user modify to change users"; allow (write, read)(groupdn="ldap:///cn=user_modify,ou=permissions,{BASEDN}");)'.format(BASEDN=self._basedn),
                # Allow user_pw_admin to nsaccountlock and password
                '(targetattr="userPassword || nsAccountLock || userCertificate || nsSshPublicKey")(targetfilter="(objectClass=nsAccount)")(version 3.0; acl "Enable user password reset"; allow (write, read)(groupdn="ldap:///cn=user_passwd_reset,ou=permissions,{BASEDN}");)'.format(BASEDN=self._basedn),
            ]
        })

        ous.create(properties = {
            'ou': 'permissions',
        })

        ous.create(properties = {
            'ou': 'services',
            'aci': [
                # Minimal service read
                '(targetattr="objectClass || description || nsUniqueId || cn || memberOf || nsAccountLock ")(targetfilter="(objectClass=netscapeServer)")(version 3.0; acl "Enable anyone service account read"; allow (read, search, compare)(userdn="ldap:///anyone");)',
            ]
        })

        # Create the demo user
        users = nsUserAccounts(self._instance, self._basedn)
        users.create(properties={
            'uid': 'demo_user',
            'cn': 'Demo User',
            'displayName': 'Demo User',
            'legalName': 'Demo User Name',
            'uidNumber': '99998',
            'gidNumber': '99998',
            'homeDirectory': '/var/empty',
            'loginShell': '/bin/false',
            'nsAccountlock': 'true'
        })

        # Create the demo group
        groups = PosixGroups(self._instance, self._basedn)
        groups.create(properties={
            'cn' : 'demo_group',
            'gidNumber': '99999'
        })

        # Create the permission groups required for the acis
        permissions = Groups(self._instance, self._basedn, rdn='ou=permissions')
        permissions.create(properties={
            'cn': 'group_admin',
        })
        permissions.create(properties={
            'cn': 'group_modify',
        })
        permissions.create(properties={
            'cn': 'user_admin',
        })
        permissions.create(properties={
            'cn': 'user_modify',
        })
        permissions.create(properties={
            'cn': 'user_passwd_reset',
        })
        permissions.create(properties={
            'cn': 'user_private_read',
        })
    def test_managed_entries(self, topology_m2):
        """Check that conflict properly resolved for operations
        with managed entries

        :id: 77f09b18-03d1-45da-940b-1ad2c2908eb4
        :setup: Two master replication, test container for entries, enable plugin logging,
                audit log, error log for replica and access log for internal
        :steps:
            1. Create ou=managed_users and ou=managed_groups under test container
            2. Configure managed entries plugin and add a template to test container
            3. Add a user to m1 and wait for replication to happen
            4. Pause replication
            5. Create a user on m1 and m2 with a same group ID on both master
            6. Create a user on m1 and m2 with a different group ID on both master
            7. Resume replication
            8. Check that the entries on both masters are the same and replication is working
        :expectedresults:
            1. It should pass
            2. It should pass
            3. It should pass
            4. It should pass
            5. It should pass
            6. It should pass
            7. It should pass
            8. It should pass
        """

        M1 = topology_m2.ms["master1"]
        M2 = topology_m2.ms["master2"]
        repl = ReplicationManager(SUFFIX)

        ous = OrganisationalUnits(M1, DEFAULT_SUFFIX)
        ou_people = ous.create(properties={'ou': 'managed_people'})
        ou_groups = ous.create(properties={'ou': 'managed_groups'})

        test_users_m1 = UserAccounts(M1, DEFAULT_SUFFIX, rdn='ou={}'.format(ou_people.rdn))
        test_users_m2 = UserAccounts(M2, DEFAULT_SUFFIX, rdn='ou={}'.format(ou_people.rdn))

        # TODO: Refactor ManagedPlugin class  functionality (also add configs and templates)
        conts = nsContainers(M1, SUFFIX)
        template = conts.create(properties={
                                 'objectclass': 'top mepTemplateEntry extensibleObject'.split(),
                                 'cn': 'MEP Template',
                                 'mepRDNAttr': 'cn',
                                 'mepStaticAttr': ['objectclass: posixGroup', 'objectclass: extensibleObject'],
                                 'mepMappedAttr': ['cn: $uid', 'uid: $cn', 'gidNumber: $uidNumber']
                                })
        repl.test_replication(M1, M2)

        for inst in topology_m2.ms.values():
            conts = nsContainers(inst, "cn={},{}".format(PLUGIN_MANAGED_ENTRY, DN_PLUGIN))
            conts.create(properties={'objectclass': 'top extensibleObject'.split(),
                                     'cn': 'config',
                                     'originScope': ou_people.dn,
                                     'originFilter': 'objectclass=posixAccount',
                                     'managedBase': ou_groups.dn,
                                     'managedTemplate': template.dn})
            inst.restart()

        _create_user(test_users_m1, 1, 1)

        topology_m2.pause_all_replicas()

        _create_user(test_users_m1, 2, 2, sleep=True)
        _create_user(test_users_m2, 2, 2, sleep=True)

        _create_user(test_users_m1, 3, 3, sleep=True)
        _create_user(test_users_m2, 3, 33)

        topology_m2.resume_all_replicas()

        repl.test_replication_topology(topology_m2)

        user_dns_m1 = [user.dn for user in test_users_m1.list()]
        user_dns_m2 = [user.dn for user in test_users_m2.list()]
        assert set(user_dns_m1) == set(user_dns_m2)
    def _apply(self):
        # Create the base domain object
        domain = Domain(self._instance, dn=self._basedn)
        # Explode the dn to get the first bit.
        avas = dn.str2dn(self._basedn)
        dc_ava = avas[0][0][1]

        domain.create(properties={
            # I think in python 2 this forces unicode return ...
            'dc': dc_ava,
            'description': self._basedn,
            'aci' : '(targetattr ="*")(version 3.0;acl "Directory Administrators Group";allow (all) (groupdn = "ldap:///cn=Directory Administrators,{BASEDN}");)'.format(BASEDN=self._basedn)
            })
        # Create the OUs
        ous = OrganisationalUnits(self._instance, self._basedn)
        ous.create(properties = {
            'ou': 'Groups',
        })
        ous.create(properties = {
            'ou': 'People',
            'aci' : [
                '(targetattr ="userpassword || telephonenumber || facsimiletelephonenumber")(version 3.0;acl "Allow self entry modification";allow (write)(userdn = "ldap:///self");)',
                '(targetattr !="cn || sn || uid")(targetfilter ="(ou=Accounting)")(version 3.0;acl "Accounting Managers Group Permissions";allow (write)(groupdn = "ldap:///cn=Accounting Managers,ou=groups,{BASEDN}");)'.format(BASEDN=self._basedn),
                '(targetattr !="cn || sn || uid")(targetfilter ="(ou=Human Resources)")(version 3.0;acl "HR Group Permissions";allow (write)(groupdn = "ldap:///cn=HR Managers,ou=groups,{BASEDN}");)'.format(BASEDN=self._basedn),
                '(targetattr !="cn ||sn || uid")(targetfilter ="(ou=Product Testing)")(version 3.0;acl "QA Group Permissions";allow (write)(groupdn = "ldap:///cn=QA Managers,ou=groups,{BASEDN}");)'.format(BASEDN=self._basedn),
                '(targetattr !="cn || sn || uid")(targetfilter ="(ou=Product Development)")(version 3.0;acl "Engineering Group Permissions";allow (write)(groupdn = "ldap:///cn=PD Managers,ou=groups,{BASEDN}");)'.format(BASEDN=self._basedn),
            ]
        })
        ous.create(properties = {
            'ou': 'Special Users',
            'description' : 'Special Administrative Accounts',
        })
        # Create the groups.
        ugs = UniqueGroups(self._instance, self._basedn)
        ugs.create(properties = {
            'cn': 'Accounting Managers',
            'description': 'People who can manage accounting entries',
            'ou': 'groups',
            'uniqueMember' : self._instance.binddn,
        })
        ugs.create(properties = {
            'cn': 'HR Managers',
            'description': 'People who can manage HR entries',
            'ou': 'groups',
            'uniqueMember' : self._instance.binddn,
        })
        ugs.create(properties = {
            'cn': 'QA Managers',
            'description': 'People who can manage QA entries',
            'ou': 'groups',
            'uniqueMember' : self._instance.binddn,
        })
        ugs.create(properties = {
            'cn': 'PD Managers',
            'description': 'People who can manage engineer entries',
            'ou': 'groups',
            'uniqueMember' : self._instance.binddn,
        })
        # Create the directory Admin group.
        # We can't use the group factory here, as we need a custom DN override.
        da_ug = UniqueGroup(self._instance)
        da_ug._dn = 'cn=Directory Administrators,%s' % self._basedn
        da_ug.create(properties={
            'cn': 'Directory Administrators',
            'uniqueMember' : self._instance.binddn,
        })
def test_repl_modrdn(topo_m2):
    """Test that replicated MODRDN does not break replication

    :id: a3e17698-9eb4-41e0-b537-8724b9915fa6
    :setup: Two masters replication setup
    :steps:
        1. Add 3 test OrganisationalUnits A, B and C
        2. Add 1 test user under OU=A
        3. Add same test user under OU=B
        4. Stop Replication
        5. Apply modrdn to M1 - move test user from OU A -> C
        6. Apply modrdn on M2 - move test user from OU B -> C
        7. Start Replication
        8. Check that there should be only one test entry under ou=C on both masters
        9. Check that the replication is working fine both ways M1 <-> M2
    :expectedresults:
        1. This should pass
        2. This should pass
        3. This should pass
        4. This should pass
        5. This should pass
        6. This should pass
        7. This should pass
        8. This should pass
        9. This should pass
    """

    master1 = topo_m2.ms["master1"]
    master2 = topo_m2.ms["master2"]

    repl = ReplicationManager(DEFAULT_SUFFIX)

    log.info(
        "Add test entries - Add 3 OUs and 2 same users under 2 different OUs")
    OUs = OrganisationalUnits(master1, DEFAULT_SUFFIX)
    OU_A = OUs.create(properties={
        'ou': 'A',
        'description': 'A',
    })
    OU_B = OUs.create(properties={
        'ou': 'B',
        'description': 'B',
    })
    OU_C = OUs.create(properties={
        'ou': 'C',
        'description': 'C',
    })

    users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou={}'.format(OU_A.rdn))
    tuser_A = users.create(properties=TEST_USER_PROPERTIES)

    users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou={}'.format(OU_B.rdn))
    tuser_B = users.create(properties=TEST_USER_PROPERTIES)

    repl.test_replication(master1, master2)
    repl.test_replication(master2, master1)

    log.info("Stop Replication")
    topo_m2.pause_all_replicas()

    log.info("Apply modrdn to M1 - move test user from OU A -> C")
    master1.rename_s(tuser_A.dn,
                     'uid=testuser1',
                     newsuperior=OU_C.dn,
                     delold=1)

    log.info("Apply modrdn on M2 - move test user from OU B -> C")
    master2.rename_s(tuser_B.dn,
                     'uid=testuser1',
                     newsuperior=OU_C.dn,
                     delold=1)

    log.info("Start Replication")
    topo_m2.resume_all_replicas()

    log.info("Wait for sometime for repl to resume")
    repl.test_replication(master1, master2)
    repl.test_replication(master2, master1)

    log.info(
        "Check that there should be only one test entry under ou=C on both masters"
    )
    users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou={}'.format(OU_C.rdn))
    assert len(users.list()) == 1

    users = UserAccounts(master2, DEFAULT_SUFFIX, rdn='ou={}'.format(OU_C.rdn))
    assert len(users.list()) == 1

    log.info("Check that the replication is working fine both ways, M1 <-> M2")
    repl.test_replication(master1, master2)
    repl.test_replication(master2, master1)
Example #10
0
 def fin():
     log.info('Deleting user {}'.format(BN))
     topology_st.standalone.delete_s(BN)
     ous = OrganisationalUnits(topology_st.standalone, DEFAULT_SUFFIX)
     ou_people = ous.get('people')
     ou_people.remove('aci', BN_ACI)