From 459f73835de1be34bd9c9f1636ade92fd884d9ca Mon Sep 17 00:00:00 2001
From: Anuj Borah <aborah@redhat.com>
Date: Feb 20 2019 02:44:30 +0000
Subject: Issue: 50112 - Port ACI test suit from TET to python3(modify)


Port ACI test suit from TET to python3(modify)

https://pagure.io/389-ds-base/issue/50112

Reviewed by: William Brown

---

diff --git a/dirsrvtests/tests/suites/acl/modify_test.py b/dirsrvtests/tests/suites/acl/modify_test.py
new file mode 100644
index 0000000..8f9054b
--- /dev/null
+++ b/dirsrvtests/tests/suites/acl/modify_test.py
@@ -0,0 +1,574 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2019 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ----
+
+
+import pytest, os, ldap
+from lib389._constants import DEFAULT_SUFFIX, PW_DM
+from lib389.idm.user import UserAccount
+from lib389.idm.account import Anonymous
+from lib389.idm.group import Group, UniqueGroup
+from lib389.idm.organizationalunit import OrganizationalUnit
+from lib389.idm.group import Groups
+from lib389.topologies import topology_st as topo
+from lib389.idm.domain import Domain
+
+
+CONTAINER_1_DELADD = "ou=Product Development,{}".format(DEFAULT_SUFFIX)
+CONTAINER_2_DELADD = "ou=Accounting,{}".format(DEFAULT_SUFFIX)
+USER_DELADD = "cn=Jeff Vedder,{}".format(CONTAINER_1_DELADD)
+USER_WITH_ACI_DELADD = "cn=Sam Carter,{}".format(CONTAINER_2_DELADD)
+KIRSTENVAUGHAN = "cn=Kirsten Vaughan, ou=Human Resources, {}".format(DEFAULT_SUFFIX)
+HUMAN_OU_GLOBAL = "ou=Human Resources,{}".format(DEFAULT_SUFFIX)
+
+
+@pytest.fixture(scope="function")
+def cleanup_tree(request, topo):
+
+    def fin():
+        for i in [USER_DELADD, USER_WITH_ACI_DELADD, KIRSTENVAUGHAN, CONTAINER_1_DELADD, CONTAINER_2_DELADD, HUMAN_OU_GLOBAL]:
+            try:
+                UserAccount(topo.standalone, i).delete()
+            except:
+                pass
+
+    request.addfinalizer(fin)
+
+
+@pytest.fixture(scope="function")
+def aci_of_user(request, topo):
+    aci_list = Domain(topo.standalone, DEFAULT_SUFFIX).get_attr_vals('aci')
+
+    def finofaci():
+        domain = Domain(topo.standalone, DEFAULT_SUFFIX)
+        domain.set('aci', None)
+        for i in aci_list:
+            domain.add("aci", i)
+
+    request.addfinalizer(finofaci)
+
+
+def test_allow_write_access_to_targetattr_with_a_single_attribute(
+        topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 1 Allow write access to targetattr with a single attribute
+    :id:620d7b82-7abf-11e8-a4db-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(targetattr = "title")(version 3.0; acl "ACI NAME"; allow (write) (userdn = "ldap:///anyone") ;)'
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    ou = OrganizationalUnit(topo.standalone, "ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'Product Development'})
+
+    properties = {
+            'uid': 'Jeff Vedder',
+            'cn': 'Jeff Vedder',
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + 'JeffVedder',
+            'userPassword': PW_DM
+        }
+    user = UserAccount(topo.standalone, "cn=Jeff Vedder,ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    # Allow write access to targetattr with a single attribute
+    conn = Anonymous(topo.standalone).bind()
+    ua = UserAccount(conn, USER_DELADD)
+    ua.add("title", "Architect")
+    assert ua.get_attr_val('title')
+    ua.remove("title", "Architect")
+
+
+def test_allow_write_access_to_targetattr_with_multiple_attibutes(
+        topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 2 Allow write access to targetattr with multiple attibutes
+    :id:6b9f05c6-7abf-11e8-9ba1-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(targetattr = "telephonenumber || roomnumber")(version 3.0; acl "ACI NAME"; allow (write) (userdn = "ldap:///anyone") ;)'
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    ou = OrganizationalUnit(topo.standalone, "ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'Product Development'})
+
+    properties = {
+        'uid': 'Jeff Vedder',
+        'cn': 'Jeff Vedder',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'JeffVedder',
+        'userPassword': PW_DM
+    }
+    user = UserAccount(topo.standalone, "cn=Jeff Vedder,ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    # Allow write access to targetattr with multiple attibutes
+    conn = Anonymous(topo.standalone).bind()
+    ua = UserAccount(conn, USER_DELADD)
+    ua.add("telephonenumber", "+1 408 555 1212")
+    assert ua.get_attr_val('telephonenumber')
+    ua.add("roomnumber", "101")
+    assert ua.get_attr_val('roomnumber')
+
+
+def test_allow_write_access_to_userdn_all(topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 3 Allow write access to userdn 'all'
+    :id:70c58818-7abf-11e8-afa1-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(targetattr = "*")(version 3.0; acl "ACI NAME"; allow (write) (userdn = "ldap:///all") ;)'
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    for i in ['Product Development', 'Accounting']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+
+    for i in ['Jeff Vedder,ou=Product Development', 'Sam Carter,ou=Accounting']:
+        properties = {
+            'uid': i,
+            'cn': i,
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + i,
+            'userPassword': PW_DM
+        }
+        user = UserAccount(topo.standalone, "cn={},{}".format(i, DEFAULT_SUFFIX))
+        user.create(properties=properties)
+
+    # Allow write access to userdn 'all'
+    conn = Anonymous(topo.standalone).bind()
+    with pytest.raises(ldap.INSUFFICIENT_ACCESS):
+        UserAccount(conn, USER_DELADD).add("title", "Architect")
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    UserAccount(conn, USER_DELADD).add("title", "Architect")
+    assert UserAccount(conn, USER_DELADD).get_attr_val('title')
+
+
+def test_allow_write_access_to_userdn_with_wildcards_in_dn(
+        topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 4 Allow write access to userdn with wildcards in DN
+    :id:766c2312-7abf-11e8-b57d-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(targetattr = "*")(version 3.0; acl "ACI NAME"; allow (write)(userdn = "ldap:///cn=*, ou=Product Development,{}") ;)'.format(DEFAULT_SUFFIX)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    ou = OrganizationalUnit(topo.standalone, "ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'Product Development'})
+
+    properties = {
+        'uid': 'Jeff Vedder',
+        'cn': 'Jeff Vedder',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'JeffVedder',
+        'userPassword': PW_DM
+    }
+    user = UserAccount(topo.standalone, "cn=Jeff Vedder,ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    conn = UserAccount(topo.standalone, USER_DELADD).bind(PW_DM)
+    # Allow write access to userdn with wildcards in DN
+    ua = UserAccount(conn, USER_DELADD)
+    ua.add("title", "Architect")
+    assert ua.get_attr_val('title')
+
+
+def test_allow_write_access_to_userdn_with_multiple_dns(topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 5 Allow write access to userdn with multiple DNs
+    :id:7aae760a-7abf-11e8-bc3a-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(targetattr = "*")(version 3.0; acl "ACI NAME"; allow (write)(userdn = "ldap:///{} || ldap:///{}") ;)'.format(USER_DELADD, USER_WITH_ACI_DELADD)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    for i in ['Product Development', 'Accounting', 'Human Resources']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+
+    for i in ['Jeff Vedder,ou=Product Development', 'Sam Carter,ou=Accounting', 'Kirsten Vaughan, ou=Human Resources']:
+        properties = {
+            'uid': i,
+            'cn': i,
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + i,
+            'userPassword': PW_DM
+        }
+        user = UserAccount(topo.standalone, "cn={},{}".format(i, DEFAULT_SUFFIX))
+        user.create(properties=properties)
+
+    conn = UserAccount(topo.standalone, USER_DELADD).bind(PW_DM)
+    # Allow write access to userdn with multiple DNs
+    ua = UserAccount(conn, KIRSTENVAUGHAN)
+    ua.add("title", "Architect")
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # Allow write access to userdn with multiple DNs
+    ua = UserAccount(conn, USER_DELADD)
+    ua.add("title", "Architect")
+    assert ua.get_attr_val('title')
+    
+
+def test_allow_write_access_to_target_with_wildcards(topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 6 Allow write access to target with wildcards
+    :id:825fe884-7abf-11e8-8541-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(target = ldap:///{})(targetattr = "*")(version 3.0; acl "ACI NAME"; allow (write) (userdn = "ldap:///anyone") ;)'.format(DEFAULT_SUFFIX)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    for i in ['Product Development', 'Accounting', 'Human Resources']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+
+    for i in ['Jeff Vedder,ou=Product Development', 'Sam Carter,ou=Accounting', 'Kirsten Vaughan, ou=Human Resources']:
+        properties = {
+            'uid': i,
+            'cn': i,
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + i,
+            'userPassword': PW_DM
+        }
+        user = UserAccount(topo.standalone, "cn={},{}".format(i, DEFAULT_SUFFIX))
+        user.create(properties=properties)
+
+    conn = UserAccount(topo.standalone, USER_DELADD).bind(PW_DM)
+    # Allow write access to target with wildcards
+    ua = UserAccount(conn, KIRSTENVAUGHAN)
+    ua.add("title", "Architect")
+    assert ua.get_attr_val('title')
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # Allow write access to target with wildcards
+    ua = UserAccount(conn, USER_DELADD)
+    ua.add("title", "Architect")
+    assert ua.get_attr_val('title')
+
+
+def test_allow_write_access_to_userdnattr(topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 7 Allow write access to userdnattr
+    :id:86b418f6-7abf-11e8-ae28-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(target = ldap:///{})(targetattr=*)(version 3.0; acl "$tet_thistest";allow (write) (userdn = "ldap:///anyone"); )'.format(DEFAULT_SUFFIX)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    for i in ['Product Development', 'Accounting']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+
+    for i in ['Jeff Vedder,ou=Product Development', 'Sam Carter,ou=Accounting']:
+        properties = {
+            'uid': i,
+            'cn': i,
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + i,
+            'userPassword': PW_DM
+        }
+        user = UserAccount(topo.standalone, "cn={},{}".format(i, DEFAULT_SUFFIX))
+        user.create(properties=properties)
+
+    UserAccount(topo.standalone, USER_WITH_ACI_DELADD).add('manager', USER_WITH_ACI_DELADD)
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # Allow write access to userdnattr
+    ua = UserAccount(conn, USER_DELADD)
+    ua.add('uid', 'scoobie')
+    assert ua.get_attr_val('uid')
+    ua.add('uid', 'jvedder')
+    assert ua.get_attr_val('uid')
+
+
+def test_allow_selfwrite_access_to_anyone(topo, aci_of_user, cleanup_tree):
+    """
+       Modify Test 8 Allow selfwrite access to anyone
+       :id:8b3becf0-7abf-11e8-ac34-8c16451d917b
+       :setup: server
+       :steps:
+           1. Add test entry
+           2. Add ACI
+           3. User should follow ACI role
+       :expectedresults:
+           1. Entry should be added
+           2. Operation should  succeed
+           3. Operation should  succeed
+    """
+    groups = Groups(topo.standalone, DEFAULT_SUFFIX)
+    group = groups.create(properties={"cn": "group1",
+                        "description": "testgroup"})
+
+    ACI_BODY = '(target = ldap:///cn=group1,ou=Groups,{})(targetattr = "member")(version 3.0; acl "ACI NAME"; allow (selfwrite) (userdn = "ldap:///anyone") ;)'.format(DEFAULT_SUFFIX)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    ou = OrganizationalUnit(topo.standalone, "ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'Product Development'})
+
+    properties = {
+        'uid': 'Jeff Vedder',
+        'cn': 'Jeff Vedder',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'JeffVedder',
+        'userPassword': PW_DM
+    }
+    user = UserAccount(topo.standalone, "cn=Jeff Vedder,ou=Product Development,{}".format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    conn = UserAccount(topo.standalone, USER_DELADD).bind(PW_DM)
+    # Allow selfwrite access to anyone
+    groups = Groups(conn, DEFAULT_SUFFIX)
+    groups.list()[0].add_member(USER_DELADD)
+    group.delete()
+
+
+def test_uniquemember_should_also_be_the_owner(topo,  aci_of_user):
+    """
+    Modify Test 10 groupdnattr = \"ldap:///$BASEDN?owner\" if owner is a group, group's
+    uniquemember should also be the owner
+    :id:9456b2d4-7abf-11e8-829d-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    for i in ['ACLGroupTest']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+
+    ou = OrganizationalUnit(topo.standalone, "ou=ACLDevelopment,{}".format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'ACLDevelopment'})
+    ou.set('aci','(targetattr="*")(version 3.0; acl "groupdnattr acl"; '
+                 'allow (all)groupdnattr = "ldap:///{}?owner";)'.format(DEFAULT_SUFFIX))
+
+    grp = UniqueGroup(topo.standalone, "uid=anuj,ou=ACLDevelopment, {}".format(DEFAULT_SUFFIX))
+    user_props = (
+        {'sn': 'Borah',
+         'cn': 'Anuj',
+         'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'groupofUniquenames'],
+         'userpassword': PW_DM,
+         'givenname': 'Anuj',
+         'ou': ['ACLDevelopment', 'People'],
+         'roomnumber': '123',
+         'uniquemember': 'cn=mandatory member'
+         }
+    )
+    grp.create(properties=user_props)
+
+    grp = UniqueGroup(topo.standalone, "uid=2ishani,ou=ACLDevelopment, {}".format(DEFAULT_SUFFIX))
+    user_props = (
+        {'sn': 'Borah',
+         'cn': '2ishani',
+         'objectclass': ['top', 'person','organizationalPerson', 'inetOrgPerson', 'groupofUniquenames'],
+         'userpassword': PW_DM,
+         'givenname': '2ishani',
+         'ou': ['ACLDevelopment', 'People'],
+         'roomnumber': '1234',
+         'uniquemember': 'cn=mandatory member', "owner": "cn=group4, ou=ACLGroupTest, {}".format(DEFAULT_SUFFIX)
+         }
+    )
+    grp.create(properties=user_props)
+
+    grp = UniqueGroup(topo.standalone, 'cn=group1,ou=ACLGroupTest,'+DEFAULT_SUFFIX)
+    grp.create(properties={'cn': 'group1',
+                           'ou': 'groups'})
+    grp.set('uniquemember', ["cn=group2, ou=ACLGroupTest, {}".format(DEFAULT_SUFFIX),
+                             "cn=group3, ou=ACLGroupTest, {}".format(DEFAULT_SUFFIX)])
+
+    grp = UniqueGroup(topo.standalone, 'cn=group3,ou=ACLGroupTest,' + DEFAULT_SUFFIX)
+    grp.create(properties={'cn': 'group3',
+                           'ou': 'groups'})
+    grp.set('uniquemember', ["cn=group4, ou=ACLGroupTest, {}".format(DEFAULT_SUFFIX)])
+
+    grp = UniqueGroup(topo.standalone, 'cn=group4,ou=ACLGroupTest,' + DEFAULT_SUFFIX)
+    grp.create(properties={
+        'cn': 'group4',
+        'ou': 'groups'})
+    grp.set('uniquemember', ["uid=anuj, ou=ACLDevelopment, {}".format(DEFAULT_SUFFIX)])
+
+    #uniquemember should also be the owner
+    conn = UserAccount(topo.standalone, "uid=anuj,ou=ACLDevelopment, {}".format(DEFAULT_SUFFIX)).bind(PW_DM)
+    ua = UserAccount(conn, "uid=2ishani, ou=ACLDevelopment, {}".format(DEFAULT_SUFFIX))
+    ua.add('roomnumber', '9999')
+    assert ua.get_attr_val('roomnumber')
+
+    for DN in ["cn=group4,ou=ACLGroupTest,{}".format(DEFAULT_SUFFIX),
+               "cn=group3,ou=ACLGroupTest,{}".format(DEFAULT_SUFFIX),
+               "cn=group1,ou=ACLGroupTest,{}".format(DEFAULT_SUFFIX),
+               "uid=2ishani,ou=ACLDevelopment,{}".format(DEFAULT_SUFFIX),
+               "uid=anuj,ou=ACLDevelopment,{}".format(DEFAULT_SUFFIX), "ou=ACLDevelopment,{}".format(DEFAULT_SUFFIX),
+               "ou=ACLGroupTest, {}".format(DEFAULT_SUFFIX)]:
+        UserAccount(topo.standalone, DN).delete()
+
+
+def test_aci_with_both_allow_and_deny(topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 12 aci with both allow and deny
+    :id:9dcfe902-7abf-11e8-86dc-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    ACI_BODY = '(targetattr = "*")(version 3.0; acl "ACI NAME"; deny (read, search)userdn = "ldap:///{}"; allow (all) userdn = "ldap:///{}" ;)'.format(USER_WITH_ACI_DELADD, USER_DELADD)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    for i in ['Product Development', 'Accounting']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+
+    for i in ['Jeff Vedder,ou=Product Development', 'Sam Carter,ou=Accounting']:
+        properties = {
+            'uid': i,
+            'cn': i,
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + i,
+            'userPassword': PW_DM
+        }
+        user = UserAccount(topo.standalone, "cn={},{}".format(i, DEFAULT_SUFFIX))
+        user.create(properties=properties)
+
+    conn = UserAccount(topo.standalone, USER_DELADD).bind(PW_DM)
+    # aci with both allow and deny, testing allow
+    assert UserAccount(conn, USER_WITH_ACI_DELADD).get_attr_val('uid')
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # aci with both allow and deny, testing deny
+    with pytest.raises(IndexError):
+        UserAccount(conn, USER_WITH_ACI_DELADD).get_attr_val('uid')
+
+
+def test_allow_owner_to_modify_entry(topo, aci_of_user, cleanup_tree):
+    """
+    Modify Test 14 allow userdnattr = owner to modify entry
+    :id:aa302090-7abf-11e8-811a-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    grp = UniqueGroup(topo.standalone, 'cn=intranet,' + DEFAULT_SUFFIX)
+    grp.create(properties={
+        'cn': 'intranet',
+        'ou': 'groups'})
+    grp.set('owner', USER_WITH_ACI_DELADD)
+
+    ACI_BODY = '(target ="ldap:///cn=intranet, {}") (targetattr ="*")(targetfilter ="(objectclass=groupOfUniqueNames)") (version 3.0;acl "$tet_thistest";allow(read, write, delete, search, compare, add) (userdnattr = "owner");)'.format(DEFAULT_SUFFIX)
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", ACI_BODY)
+
+    for i in ['Product Development', 'Accounting']:
+        ou = OrganizationalUnit(topo.standalone, "ou={},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': i})
+    for i in ['Jeff Vedder,ou=Product Development', 'Sam Carter,ou=Accounting']:
+        properties = {
+            'uid': i,
+            'cn': i,
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + i,
+            'userPassword': PW_DM
+        }
+        user = UserAccount(topo.standalone, "cn={},{}".format(i, DEFAULT_SUFFIX))
+        user.create(properties=properties)
+
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # allow userdnattr = owner to modify entry
+    ua = UserAccount(conn, 'cn=intranet,dc=example,dc=com')
+    ua.set('uniquemember', "cn=Andy Walker, ou=Accounting,dc=example,dc=com")
+    assert ua.get_attr_val('uniquemember')
+
+
+if __name__ == "__main__":
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s -v %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/suites/acl/modrdn_test.py b/dirsrvtests/tests/suites/acl/modrdn_test.py
new file mode 100644
index 0000000..c395e0b
--- /dev/null
+++ b/dirsrvtests/tests/suites/acl/modrdn_test.py
@@ -0,0 +1,298 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2019 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ----
+
+import pytest, os, ldap
+from lib389._constants import DEFAULT_SUFFIX, PW_DM
+from lib389.idm.user import UserAccount
+from lib389.idm.account import Anonymous
+from lib389.idm.group import Group, UniqueGroup
+from lib389.idm.organizationalunit import OrganizationalUnit, OrganizationalUnits
+from lib389.topologies import topology_st as topo
+from lib389.idm.domain import Domain
+
+
+CONTAINER_1_DELADD = "ou=Product Development,{}".format(DEFAULT_SUFFIX)
+CONTAINER_2_DELADD = "ou=Accounting,{}".format(DEFAULT_SUFFIX)
+USER_DELADD = "cn=Jeff Vedder,{}".format(CONTAINER_1_DELADD)
+USER_WITH_ACI_DELADD = "cn=Sam Carter,{}".format(CONTAINER_2_DELADD)
+DYNAMIC_MODRDN = "cn=Test DYNAMIC_MODRDN Group 70, {}".format(DEFAULT_SUFFIX)
+SAM_DAMMY_MODRDN = "cn=Sam Carter1,ou=Accounting,{}".format(DEFAULT_SUFFIX)
+TRAC340_MODRDN = "cn=TRAC340_MODRDN,{}".format(DEFAULT_SUFFIX)
+NEWENTRY9_MODRDN = "cn=NEWENTRY9_MODRDN,{}".format("ou=People,{}".format(DEFAULT_SUFFIX))
+OU0_OU_MODRDN = "ou=OU0,{}".format(DEFAULT_SUFFIX)
+OU2_OU_MODRDN = "ou=OU2,{}".format(DEFAULT_SUFFIX)
+
+
+@pytest.fixture(scope="function")
+def aci_of_user(request, topo):
+    aci_list = Domain(topo.standalone, DEFAULT_SUFFIX).get_attr_vals('aci')
+
+    def finofaci():
+        domain = Domain(topo.standalone, DEFAULT_SUFFIX)
+        domain.set('aci', None)
+        for i in aci_list:
+            domain.add("aci", i)
+
+    request.addfinalizer(finofaci)
+
+
+@pytest.fixture(scope="function")
+def _add_user(request, topo):
+    ou = OrganizationalUnit(topo.standalone, 'ou=Product Development,{}'.format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'Product Development'})
+
+    ou = OrganizationalUnit(topo.standalone, 'ou=Accounting,{}'.format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'Accounting'})
+
+    groups = Group(topo.standalone, DYNAMIC_MODRDN)
+    group_properties = {"cn": "Test DYNAMIC_MODRDN Group 70",
+                        "objectclass": ["top", 'groupofURLs'],
+                        'memberURL': 'ldap:///{}??base?(cn=*)'.format(USER_WITH_ACI_DELADD)}
+    groups.create(properties=group_properties)
+
+    properties = {
+        'uid': 'Jeff Vedder',
+        'cn': 'Jeff Vedder',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'JeffVedder',
+        'userPassword': PW_DM
+    }
+    user = UserAccount(topo.standalone, 'cn=Jeff Vedder,ou=Product Development,{}'.format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    properties = {
+        'uid': 'Sam Carter',
+        'cn': 'Sam Carter',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'SamCarter',
+        'userPassword': PW_DM
+    }
+    user = UserAccount(topo.standalone, 'cn=Sam Carter,ou=Accounting,{}'.format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    def fin():
+        for DN in [USER_DELADD,USER_WITH_ACI_DELADD,DYNAMIC_MODRDN,CONTAINER_2_DELADD,CONTAINER_1_DELADD]:
+            UserAccount(topo.standalone, DN).delete()
+
+    request.addfinalizer(fin)
+
+
+def test_allow_write_privilege_to_anyone(topo, _add_user, aci_of_user):
+    """
+    Modrdn Test 1 Allow write privilege to anyone
+    :id: 4406f12e-7932-11e8-9dea-8c16451d917b
+    :setup: server
+    :steps:
+        1. Add test entry
+        2. Add ACI
+        3. User should follow ACI role
+    :expectedresults:
+        1. Entry should be added
+        2. Operation should  succeed
+        3. Operation should  succeed
+    """
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci",
+        '(target ="ldap:///{}")(targetattr=*)(version 3.0;acl "$tet_thistest";allow '
+        '(write) (userdn = "ldap:///anyone");)'.format(DEFAULT_SUFFIX))
+    conn = Anonymous(topo.standalone).bind()
+    # Allow write privilege to anyone
+    useraccount = UserAccount(conn, USER_WITH_ACI_DELADD)
+    useraccount.rename("cn=Jeff Vedder")
+    assert 'cn=Jeff Vedder,ou=Accounting,dc=example,dc=com' == useraccount.dn
+    useraccount = UserAccount(conn, "cn=Jeff Vedder,ou=Accounting,dc=example,dc=com")
+    useraccount.rename("cn=Sam Carter")
+    assert 'cn=Sam Carter,ou=Accounting,dc=example,dc=com' == useraccount.dn
+
+
+def test_allow_write_privilege_to_dynamic_group_with_scope_set_to_base_in_ldap_url(
+    topo, _add_user, aci_of_user
+):
+    """
+        Modrdn Test 2 Allow write privilege to DYNAMIC_MODRDN group with scope set to base in LDAP URL
+        :id: 4c0f8c00-7932-11e8-8398-8c16451d917b
+        :setup: server
+        :steps:
+            1. Add test entry
+            2. Add ACI
+            3. User should follow ACI role
+        :expectedresults:
+            1. Entry should be added
+            2. Operation should  succeed
+            3. Operation should  succeed
+    """
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci",'(target = ldap:///{})(targetattr=*)(version 3.0; acl "$tet_thistest"; allow(all)(groupdn = "ldap:///{}"); )'.format(DEFAULT_SUFFIX, DYNAMIC_MODRDN))
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # Allow write privilege to DYNAMIC_MODRDN group with scope set to base in LDAP URL
+    useraccount = UserAccount(conn, USER_DELADD)
+    useraccount.rename("cn=Jeffbo Vedder")
+    assert 'cn=Jeffbo Vedder,ou=Product Development,dc=example,dc=com' == useraccount.dn
+    useraccount = UserAccount(conn, "cn=Jeffbo Vedder,{}".format(CONTAINER_1_DELADD))
+    useraccount.rename("cn=Jeff Vedder")
+    assert 'cn=Jeff Vedder,ou=Product Development,dc=example,dc=com' == useraccount.dn
+
+
+def test_write_access_to_naming_atributes(topo, _add_user, aci_of_user):
+    """
+        Test for write access to naming atributes (1)
+        Test that check for add writes to the new naming attr
+        :id: 532fc630-7932-11e8-8924-8c16451d917b
+        :setup: server
+        :steps:
+            1. Add test entry
+            2. Add ACI
+            3. User should follow ACI role
+        :expectedresults:
+            1. Entry should be added
+            2. Operation should  succeed
+            3. Operation should  succeed
+    """
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", '(target ="ldap:///{}")(targetattr != "uid")(version 3.0;acl "$tet_thistest";allow (write) (userdn = "ldap:///anyone");)'.format(DEFAULT_SUFFIX))
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    #Test for write access to naming atributes
+    useraccount = UserAccount(conn, USER_WITH_ACI_DELADD)
+    with pytest.raises(ldap.INSUFFICIENT_ACCESS):
+        useraccount.rename("uid=Jeffbo Vedder")
+    
+
+def test_write_access_to_naming_atributes_two(topo, _add_user, aci_of_user):
+    """
+        Test for write access to naming atributes (2)
+        :id: 5a2077d2-7932-11e8-9e7b-8c16451d917b
+        :setup: server
+        :steps:
+            1. Add test entry
+            2. Add ACI
+            3. User should follow ACI role
+            4. Now try to modrdn it to cn, won't work if request deleteoldrdn.
+        :expectedresults:
+            1. Entry should be added
+            2. Operation should  succeed
+            3. Operation should  succeed
+            4. Operation should  not succeed
+    """
+    Domain(topo.standalone, DEFAULT_SUFFIX).add("aci", '(target ="ldap:///{}")(targetattr != "uid")(version 3.0;acl "$tet_thistest";allow (write) (userdn = "ldap:///anyone");)'.format(DEFAULT_SUFFIX))
+    properties = {
+        'uid': 'Sam Carter1',
+        'cn': 'Sam Carter1',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'SamCarter1'
+    }
+    user = UserAccount(topo.standalone, 'cn=Sam Carter1,ou=Accounting,{}'.format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+    user.set("userPassword", "password")
+    conn = UserAccount(topo.standalone, USER_WITH_ACI_DELADD).bind(PW_DM)
+    # Test for write access to naming atributes
+    useraccount = UserAccount(conn, SAM_DAMMY_MODRDN)
+    with pytest.raises(ldap.INSUFFICIENT_ACCESS):
+        useraccount.rename("uid=Jeffbo Vedder")
+    UserAccount(topo.standalone, SAM_DAMMY_MODRDN).delete()
+
+
+@pytest.mark.bz950351
+def test_access_aci_list_contains_any_deny_rule(topo, _add_user, aci_of_user):
+    """
+        Testing bug #950351:  RHDS denies MODRDN access if ACI list contains any DENY rule
+        Bug description: If you create a deny ACI for some or more attributes there is incorrect behaviour
+         as you cannot rename the entry anymore
+        :id: 62cbbb8a-7932-11e8-96a7-8c16451d917b
+        :setup: server
+        :steps:
+            1. Add test entry
+            2. Adding a new ou ou=People to $BASEDN
+            3. Adding a user NEWENTRY9_MODRDN to ou=People,$BASEDN
+            4. Adding an allow rule for NEWENTRY9_MODRDN and for others an aci deny rule
+        :expectedresults:
+            1. Entry should be added
+            2. Operation should  succeed
+            3. Operation should  succeed
+            4. Operation should  succeed
+    """
+    properties = {
+        'uid': 'NEWENTRY9_MODRDN',
+        'cn': 'NEWENTRY9_MODRDN_People',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'NEWENTRY9_MODRDN'
+    }
+    user = UserAccount(topo.standalone, 'cn=NEWENTRY9_MODRDN,ou=People,{}'.format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+    user.set("userPassword", "password")
+    user.set("telephoneNumber", "989898191")
+    user.set("mail", "anuj@anuj.com")
+    user.set("givenName", "givenName")
+    user.set("uid", "NEWENTRY9_MODRDN")
+    OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX).get('People').add("aci", ['(targetattr = "*") '
+        '(version 3.0;acl "admin";allow (all)(userdn = "ldap:///{}");)'.format(NEWENTRY9_MODRDN),
+        '(targetattr = "mail") (version 3.0;acl "deny_mail";deny (write)(userdn = "ldap:///anyone");)',
+        '(targetattr = "uid") (version 3.0;acl "allow uid";allow (write)(userdn = "ldap:///{}");)'.format(NEWENTRY9_MODRDN)])
+    UserAccount(topo.standalone, NEWENTRY9_MODRDN).replace("userpassword", "Anuj")
+    useraccount = UserAccount(topo.standalone, NEWENTRY9_MODRDN)
+    useraccount.rename("uid=newrdnchnged")
+    assert 'uid=newrdnchnged,ou=People,dc=example,dc=com' == useraccount.dn
+
+
+def test_renaming_target_entry(topo, _add_user, aci_of_user):
+    """
+        Test for renaming target entry
+        :id: 6be1d33a-7932-11e8-9115-8c16451d917b
+        :setup: server
+        :steps:
+            1. Add test entry
+            2. Create a test user entry
+            3.Create a new ou entry with an aci
+            4. Make sure uid=$MYUID has the access
+            5. Rename ou=OU0 to ou=OU1
+            6. Create another ou=OU2
+            7. Move ou=OU1 under ou=OU2
+            8. Make sure uid=$MYUID still has the access
+        :expectedresults:
+            1. Entry should be added
+            2. Operation should  succeed
+            3. Operation should  succeed
+            4. Operation should  succeed
+            5. Operation should  succeed
+            6. Operation should  succeed
+            7. Operation should  succeed
+            8. Operation should  succeed
+    """
+    properties = {
+        'uid': 'TRAC340_MODRDN',
+        'cn': 'TRAC340_MODRDN',
+        'sn': 'user',
+        'uidNumber': '1000',
+        'gidNumber': '2000',
+        'homeDirectory': '/home/' + 'TRAC340_MODRDN'
+    }
+    user = UserAccount(topo.standalone, 'cn=TRAC340_MODRDN,{}'.format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+    user.set("userPassword", "password")
+    ou = OrganizationalUnit(topo.standalone, 'ou=OU0,{}'.format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'OU0'})
+    ou.set('aci', '(targetattr=*)(version 3.0; acl "$MYUID";allow(read, search, compare) userdn = "ldap:///{}";)'.format(TRAC340_MODRDN))
+    conn = UserAccount(topo.standalone, TRAC340_MODRDN).bind(PW_DM)
+    assert OrganizationalUnits(conn, DEFAULT_SUFFIX).get('OU0')
+    # Test for renaming target entry
+    OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX).get('OU0').rename("ou=OU1")
+    assert OrganizationalUnits(conn, DEFAULT_SUFFIX).get('OU1')
+    ou = OrganizationalUnit(topo.standalone, 'ou=OU2,{}'.format(DEFAULT_SUFFIX))
+    ou.create(properties={'ou': 'OU2'})
+    # Test for renaming target entry
+    OrganizationalUnits(topo.standalone, DEFAULT_SUFFIX).get('OU1').rename("ou=OU1", newsuperior=OU2_OU_MODRDN)
+    assert OrganizationalUnits(conn, DEFAULT_SUFFIX).get('OU1')
+
+
+if __name__ == "__main__":
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s -v %s" % CURRENT_FILE)

