From 54a327359f6178db03417d996f0e4dd4c8542d19 Mon Sep 17 00:00:00 2001 From: alisha17 Date: Feb 01 2018 00:19:03 +0000 Subject: Bug Description: Add support for managing automember to dsconf Fix Description: Added the dsconf support and tests for creating, removing, editing and showing the automember definitions. https://pagure.io/lib389/issue/35 Author: Alisha Aneja Review by: ??? --- diff --git a/src/lib389/cli/dsconf b/src/lib389/cli/dsconf index b13183c..f62d3d0 100755 --- a/src/lib389/cli/dsconf +++ b/src/lib389/cli/dsconf @@ -28,6 +28,8 @@ from lib389.cli_conf.plugins import usn as cli_usn from lib389.cli_conf.plugins import rootdn_ac as cli_rootdn_ac from lib389.cli_conf.plugins import whoami as cli_whoami from lib389.cli_conf.plugins import referint as cli_referint +from lib389.cli_conf.plugins import automember as cli_automember + from lib389.cli_base import disconnect_instance, connect_instance from lib389.cli_base.dsrc import dsrc_to_ldap, dsrc_arg_concat @@ -75,7 +77,8 @@ if __name__ == '__main__': cli_rootdn_ac.create_parser(subparsers) cli_whoami.create_parser(subparsers) cli_referint.create_parser(subparsers) - + cli_automember.create_parser(subparsers) + args = parser.parse_args() if args.verbose: diff --git a/src/lib389/lib389/cli_conf/plugins/automember.py b/src/lib389/lib389/cli_conf/plugins/automember.py new file mode 100644 index 0000000..d4330c3 --- /dev/null +++ b/src/lib389/lib389/cli_conf/plugins/automember.py @@ -0,0 +1,158 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2016-2017 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- + +import ldap + +from lib389.plugins import AutoMembershipPlugin, AutoMembershipDefinition, AutoMembershipDefinitions +from lib389.cli_conf.plugin import add_generic_plugin_parsers + + +def list_definition(inst, basedn, log, args): + """ + List automember definition if instance name + is given else show all automember definitions. + + :param name: An instance + :type name: lib389.DirSrv + + """ + + automembers = AutoMembershipDefinitions(inst) + + if args.name is not None: + automember = automembers.get(args.name) + log.info(automember.display()) + else: + all_definitions = automembers.list() + + for definition in all_definitions: + log.info(definition.display()) + + +def create_definition(inst, basedn, log, args): + """ + Create automember definition. + + :param name: An instance + :type name: lib389.DirSrv + :param groupattr: autoMemberGroupingAttr value + :type groupattr: str + :param defaultgroup: autoMemberDefaultGroup value + :type defaultgroup: str + :param scope: autoMemberScope value + :type scope: str + :param filter: autoMemberFilter value + :type filter: str + + """ + automember_prop = { + 'cn': args.name, + 'autoMemberScope': args.scope, + 'autoMemberFilter': args.filter, + 'autoMemberDefaultGroup': args.defaultgroup, + 'autoMemberGroupingAttr': args.groupattr, + } + + plugin = AutoMembershipPlugin(inst) + plugin.enable() + + automembers = AutoMembershipDefinitions(inst) + + automember = automembers.create(properties=automember_prop) + log.info("Automember definition created successfully!") + + +def edit_definition(inst, basedn, log, args): + """ + Edit automember definition + + :param name: An instance + :type name: lib389.DirSrv + :param groupattr: autoMemberGroupingAttr value + :type groupattr: str + :param defaultgroup: autoMemberDefaultGroup value + :type defaultgroup: str + :param scope: autoMemberScope value + :type scope: str + :param filter: autoMemberFilter value + :type filter: str + + """ + automembers = AutoMembershipDefinitions(inst) + automember = automembers.get(args.name) + + if args.scope is not None: + automember.replace("automemberscope", args.scope) + if args.filter is not None: + automember.replace("automemberfilter", args.filter) + if args.defaultgroup is not None: + automember.replace("automemberdefaultgroup", args.defaultgroup) + if args.groupattr is not None: + automember.replace("automembergroupingattr", args.groupattr) + + log.info("Definition updated successfully.") + + +def remove_definition(inst, basedn, log, args): + """ + Remove automember definition for the given + instance. + + :param name: An instance + :type name: lib389.DirSrv + + """ + automembers = AutoMembershipDefinitions(inst) + automember = automembers.get(args.name) + + automember.delete() + log.info("Definition deleted successfully!") + + +def create_parser(subparsers): + automember_parser = subparsers.add_parser('automember', help="Manage and configure automember plugin") + + subcommands = automember_parser.add_subparsers(help='action') + + add_generic_plugin_parsers(subcommands, AutoMembershipPlugin) + + create_parser = subcommands.add_parser('create', help='Create automember definition.') + create_parser.set_defaults(func=create_definition) + + create_parser.add_argument("name", nargs='?', required=True ,help='Set cn for group entry.') + + create_parser.add_argument("--groupattr", help='Set member attribute in group entry.', default='member:dn') + + create_parser.add_argument('--defaultgroup', required=True, help='Set default group to add member to.') + + create_parser.add_argument('--scope', required=True, help='Set automember scope.') + + create_parser.add_argument('--filter', help='Set automember filter.', default= '(objectClass=*)') + + show_parser = subcommands.add_parser('list', help='List automember definition.') + show_parser.set_defaults(func=list_definition) + + show_parser.add_argument("name", nargs='?', help='Set cn for group entry.') + + edit_parser = subcommands.add_parser('edit', help='Edit automember definition.') + edit_parser.set_defaults(func=edit_definition) + + edit_parser.add_argument("name", help='Set cn for group entry.') + + edit_parser.add_argument("--groupattr", help='Set member attribute in group entry.') + + edit_parser.add_argument('--defaultgroup', help='Set default group to add member to.') + + edit_parser.add_argument('--scope', help='Set automember scope.') + + edit_parser.add_argument('--filter', help='Set automember filter.') + + remove_parser = subcommands.add_parser('remove', help='Remove automember definition.') + remove_parser.set_defaults(func=remove_definition) + + remove_parser.add_argument("name", help='Set cn for group entry.') diff --git a/src/lib389/lib389/plugins.py b/src/lib389/lib389/plugins.py index 8180e78..830ac7b 100644 --- a/src/lib389/lib389/plugins.py +++ b/src/lib389/lib389/plugins.py @@ -488,7 +488,7 @@ class AutoMembershipDefinitions(DSLdapObjects): :type basedn: str """ - def __init__(self, instance, basedn): + def __init__(self, instance, basedn="cn=Auto Membership Plugin,cn=plugins,cn=config"): super(AutoMembershipDefinitions, self).__init__(instance) self._objectclasses = ['top','autoMemberDefinition'] self._filterattrs = ['cn'] diff --git a/src/lib389/lib389/tests/cli/conf_plugins/automember_test.py b/src/lib389/lib389/tests/cli/conf_plugins/automember_test.py new file mode 100644 index 0000000..bffb34c --- /dev/null +++ b/src/lib389/lib389/tests/cli/conf_plugins/automember_test.py @@ -0,0 +1,122 @@ +import pytest +import ldap + +from lib389.tests.cli import topology as default_topology +from lib389.cli_base import LogCapture, FakeArgs +from lib389.plugins import AutoMembershipPlugin +from lib389.cli_conf.plugins import automember as automember_cli + +@pytest.fixture(scope="module") +def topology(request): + topology = default_topology(request) + + plugin = AutoMembershipPlugin(topology.standalone) + if not plugin.exists(): + plugin.create() + + # we need to restart the server after enabling the plugin + plugin.enable() + topology.standalone.restart() + topology.logcap.flush() + + return topology + + +def test_namenotexists_listdefinition(topology): + """ + Test if non existent instance raises ldap.NO_SUCH_OBJECT exception + when showing automember definition. + """ + args = FakeArgs() + + args.name = "somerandomcn" + + with pytest.raises(ldap.NO_SUCH_OBJECT): + automember_cli.list_definition(topology.standalone, None, topology.logcap.log, args) + log.info("Definition for instance {} does not exist".format(args.name)) + + +def test_createdefinition(topology): + """ + Test if new automember definition is created successfully. + """ + args = FakeArgs() + + args.name = "sometestcn" + args.scope = "ou=People,dc=example,dc=com" + args.filter = "objectclass=*" + args.groupattr = "member:dn" + args.defaultgroup = "cn=linux-group,cn=groups,dc=example,dc=com" + + automember_cli.create_definition(topology.standalone, None, topology.logcap.log, args) + assert topology.logcap.contains("Automember definition created successfully!") + + topology.logcap.flush() + + +def test_invalidattributes_createdefinition(topology): + """ + Test if invalid attributes raise ldap.INVALID_SYNTAX exception + when creating new automember definition. + """ + args = FakeArgs() + + args.name = "sometestcn" + args.scope = "someinvalidscope" + args.filter = "objectclass=*" + args.groupattr = "member:dn" + args.defaultgroup = "someinvaliddefaultgroup" + + with pytest.raises(ldap.INVALID_SYNTAX): + automember_cli.create_definition(topology.standalone, None, topology.logcap.log, args) + log.info("There are invalid attributes in the definition.") + + +def test_ifnameexists_createdefinition(topology): + """ + Test if already existing instance name raises ldap.ALREADY-EXISTS + exception when creating new automember definition. + """ + + args = FakeArgs() + + args.name = "sometestcn" + args.scope = "ou=People,dc=example,dc=com" + args.filter = "objectclass=*" + args.groupattr = "member:dn" + args.defaultgroup = "cn=windows-group,cn=groups,dc=example,dc=com" + + with pytest.raises(ldap.ALREADY_EXISTS): + automember_cli.create_definition(topology.standalone, None, topology.logcap.log, args) + log.info("Definition for instance {} already exists.".format(args.name)) + + +def test_editdefinition(topology): + """ + Test if automember definition is updated successfully. + """ + args = FakeArgs() + + args.name = "sometestcn" + args.scope = "ou=People,dc=example,dc=com" + args.filter = "objectclass=*" + args.groupattr = "member:dn" + args.defaultgroup = "cn=windows-group,cn=groups,dc=example,dc=com" + + a = automember_cli.edit_definition(topology.standalone, None, topology.logcap.log, args) + + assert topology.logcap.contains("Definition updated successfully.") + + +def test_nonexistentinstance_removedefinition(topology): + """ + Test if non existent instance definition raises NO_SUCH_OBJECT + definition when removing automember definition. + """ + args = FakeArgs() + + args.name = "randomcn" + + with pytest.raises(ldap.NO_SUCH_OBJECT): + automember_cli.remove_definition(topology.standalone, None, topology.logcap.log, args) + log.info("Definition for instance {} does not exist.".format(args.name))