URL: https://github.com/freeipa/freeipa/pull/399
Author: dkupka
 Title: #399: Certificate mapping test
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/399/head:pr399
git checkout pr399
From bdd96f302520fd9cbef19d2b2716e8c29244750d Mon Sep 17 00:00:00 2001
From: David Kupka <dku...@redhat.com>
Date: Fri, 13 Jan 2017 13:17:35 +0100
Subject: [PATCH 1/3] test_xmlrpc: tracker: Add enable and disable methods to
 tracker

Prepare tracker for easier testing of *-{en,dis}able commands.
---
 ipatests/test_xmlrpc/tracker/base.py | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/ipatests/test_xmlrpc/tracker/base.py b/ipatests/test_xmlrpc/tracker/base.py
index aa88e6b..d8cd3a6 100644
--- a/ipatests/test_xmlrpc/tracker/base.py
+++ b/ipatests/test_xmlrpc/tracker/base.py
@@ -198,6 +198,14 @@ def make_update_command(self, updates):
         """Make function that modifies the entry using ${CMD}_mod"""
         raise NotImplementedError(self._override_me_msg)
 
+    def make_enable_command(self):
+        """Make function that enables the entry using ${CMD}_enable"""
+        raise NotImplementedError(self._override_me_msg)
+
+    def make_disable_command(self):
+        """Make function that disables the entry using ${CMD}_disable"""
+        raise NotImplementedError(self._override_me_msg)
+
     def create(self):
         """Helper function to create an entry and check the result"""
         self.track_create()
@@ -285,3 +293,21 @@ def update(self, updates, expected_updates=None):
     def check_update(self, result, extra_keys=()):
         """Check the plugin's `mod` command result"""
         raise NotImplementedError(self._override_me_msg)
+
+    def enable(self):
+        command = self.make_enable_command()
+        result = command()
+        self.check_enable(result)
+
+    def check_enable(self, result):
+        """Check the plugin's `enable` command result"""
+        raise NotImplementedError(self._override_me_msg)
+
+    def disable(self):
+        command = self.make_disable_command()
+        result = command()
+        self.check_disable(result)
+
+    def check_disable(self, result):
+        """Check the plugin's `disable` command result"""
+        raise NotImplementedError(self._override_me_msg)

From b6ddcc0aaa69fcf6a17829af0385433550f3c363 Mon Sep 17 00:00:00 2001
From: David Kupka <dku...@redhat.com>
Date: Fri, 13 Jan 2017 13:22:45 +0100
Subject: [PATCH 2/3] test: certmap: Add basic tests for certmaprule commands.

https://fedorahosted.org/freeipa/ticket/6542
---
 ipatests/test_xmlrpc/objectclasses.py          |   5 +
 ipatests/test_xmlrpc/test_certmap_plugin.py    | 107 ++++++++++++++++
 ipatests/test_xmlrpc/tracker/certmap_plugin.py | 167 +++++++++++++++++++++++++
 3 files changed, 279 insertions(+)
 create mode 100644 ipatests/test_xmlrpc/test_certmap_plugin.py
 create mode 100644 ipatests/test_xmlrpc/tracker/certmap_plugin.py

diff --git a/ipatests/test_xmlrpc/objectclasses.py b/ipatests/test_xmlrpc/objectclasses.py
index 1ea020b..0a15a21 100644
--- a/ipatests/test_xmlrpc/objectclasses.py
+++ b/ipatests/test_xmlrpc/objectclasses.py
@@ -227,3 +227,8 @@
     u'top',
     u'ipaca',
 ]
+
+certmaprule = [
+    u'top',
+    u'ipacertmaprule',
+]
diff --git a/ipatests/test_xmlrpc/test_certmap_plugin.py b/ipatests/test_xmlrpc/test_certmap_plugin.py
new file mode 100644
index 0000000..9343f9a
--- /dev/null
+++ b/ipatests/test_xmlrpc/test_certmap_plugin.py
@@ -0,0 +1,107 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+import itertools
+import pytest
+
+from ipapython.dn import DN
+from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
+from ipatests.test_xmlrpc.tracker.certmap_plugin import CertmapruleTracker
+
+certmaprule_create_params = {
+        u'cn': u'test_rule',
+        u'description': u'Certificate mapping and matching rule for test '
+                        u'purposes',
+        u'ipacertmapissuer': DN('CN=CA,O=EXAMPLE.ORG'),
+        u'ipacertmapmaprule': u'arbitrary free-form mapping rule defined and '
+                              u'consumed by SSSD',
+        u'ipacertmapmatchrule': u'arbitrary free-form matching rule defined '
+                                u'and consumed by SSSD',
+        u'associateddomain': u'example.org',
+        u'ipacertmappriority': u'1',
+}
+
+certmaprule_update_params = {
+        u'description': u'Changed description',
+        u'ipacertmapissuer': DN('CN=Changed CA,O=OTHER.ORG'),
+        u'ipacertmapmaprule': u'changed arbitrary mapping rule',
+        u'ipacertmapmatchrule': u'changed arbitrary maching rule',
+        u'associateddomain': u'changed.example.org',
+        u'ipacertmappriority': u'5',
+}
+
+certmaprule_optional_params = (
+    'description',
+    'ipacertmapissuer',
+    'ipacertmapmaprule',
+    'ipacertmapmatchrule',
+    'ipaassociateddomain',
+    'ipacertmappriority',
+)
+
+def dontfill_idfn(dont_fill):
+    return u"dont_fill=({})".format(', '.join([
+        u"{}".format(d) for d in dont_fill
+    ]))
+
+
+def update_idfn(update):
+    return ', '.join(["{}: {}".format(k, v) for k, v in update.items()])
+
+
+@pytest.fixture(scope='class')
+def certmap_rule(request):
+    tracker = CertmapruleTracker(**certmaprule_create_params)
+    return tracker.make_fixture(request)
+
+
+class TestCRUD(XMLRPC_test):
+    @pytest.mark.parametrize(
+        'dont_fill',
+        itertools.chain(*[
+            itertools.combinations(certmaprule_optional_params, l)
+            for l in range(len(certmaprule_optional_params)+1)
+        ]),
+        ids=dontfill_idfn,
+    )
+    def test_create(self, dont_fill, certmap_rule):
+        certmap_rule.ensure_missing()
+        try:
+            certmap_rule.create(dont_fill)
+        finally:
+            certmap_rule.ensure_missing()
+
+    def test_retrieve(self, certmap_rule):
+        certmap_rule.ensure_exists()
+        certmap_rule.retrieve()
+
+    def test_find(self, certmap_rule):
+        certmap_rule.ensure_exists()
+        certmap_rule.find()
+
+    @pytest.mark.parametrize('update', [
+            dict(u) for l in range(1, len(certmaprule_update_params)+1)
+            for u in itertools.combinations(
+                certmaprule_update_params.items(), l)
+        ],
+        ids=update_idfn,
+    )
+    def test_update(self, update, certmap_rule):
+        certmap_rule.ensure_missing()
+        certmap_rule.ensure_exists()
+        certmap_rule.update(update, {o: [v] for o, v in update.items()})
+
+    def test_delete(self, certmap_rule):
+        certmap_rule.ensure_exists()
+        certmap_rule.delete()
+
+
+class TestEnableDisable(XMLRPC_test):
+    def test_disable(self, certmap_rule):
+        certmap_rule.ensure_exists()
+        certmap_rule.disable()
+
+    def test_enable(self, certmap_rule):
+        certmap_rule.ensure_exists()
+        certmap_rule.enable()
diff --git a/ipatests/test_xmlrpc/tracker/certmap_plugin.py b/ipatests/test_xmlrpc/tracker/certmap_plugin.py
new file mode 100644
index 0000000..76022bf
--- /dev/null
+++ b/ipatests/test_xmlrpc/tracker/certmap_plugin.py
@@ -0,0 +1,167 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+from ipapython.dn import DN
+from ipatests.test_xmlrpc.tracker.base import Tracker
+from ipatests.test_xmlrpc import objectclasses
+from ipatests.util import assert_deepequal
+
+
+class CertmapruleTracker(Tracker):
+    """ Tracker for testin certmaprule plugin """
+    retrieve_keys = {
+        u'dn',
+        u'cn',
+        u'description',
+        u'ipacertmapissuer',
+        u'ipacertmapmaprule',
+        u'ipacertmapmatchrule',
+        u'associateddomain',
+        u'ipacertmappriority',
+        u'ipaenabledflag'
+    }
+    retrieve_all_keys = retrieve_keys | {u'objectclass'}
+    create_keys = retrieve_keys | {u'objectclass'}
+    update_keys = retrieve_keys - {u'dn'}
+
+    def __init__(self, cn, description, ipacertmapissuer, ipacertmapmaprule,
+                 ipacertmapmatchrule, associateddomain, ipacertmappriority,
+                 default_version=None):
+        super(CertmapruleTracker, self).__init__(
+            default_version=default_version)
+
+        self.dn = DN((u'cn', cn,),
+                     self.api.env.container_certmaprules,
+                     self.api.env.basedn)
+        self.options = {
+            u'description': description,
+            u'ipacertmapissuer': ipacertmapissuer,
+            u'ipacertmapmaprule': ipacertmapmaprule,
+            u'ipacertmapmatchrule': ipacertmapmatchrule,
+            u'associateddomain': associateddomain,
+            u'ipacertmappriority': ipacertmappriority,
+        }
+
+    def make_create_command(self, dont_fill=()):
+        kwargs = {k: v for k, v in self.options.items() if k not in dont_fill}
+
+        return self.make_command('certmaprule_add', self.name, **kwargs)
+
+    def track_create(self, dont_fill=()):
+        self.attrs = {
+            'dn': self.dn,
+            'cn': [self.name],
+            'ipaenabledflag': [u'TRUE'],
+            'objectclass': objectclasses.certmaprule,
+        }
+        self.attrs.update({
+            k: [v] for k, v in self.options.items() if k not in dont_fill
+        })
+        self.exists = True
+
+    def check_create(self, result):
+        assert_deepequal(dict(
+            value=self.name,
+            summary=u'Added Certificate Identity Mapping Rule "{}"'
+                    u''.format(self.name),
+            result=self.filter_attrs(self.create_keys),
+        ), result)
+
+    def create(self, dont_fill=()):
+        self.track_create(dont_fill)
+        command = self.make_create_command(dont_fill)
+        result = command()
+        self.check_create(result)
+
+    def make_delete_command(self):
+        return self.make_command('certmaprule_del', self.name)
+
+    def check_delete(self, result):
+        assert_deepequal(
+            dict(
+                value=[self.name],
+                summary=u'Deleted Certificate Identity Mapping Rule "{}"'
+                        ''.format(self.name),
+                result=dict(failed=[]),
+            ),
+            result
+        )
+
+    def make_retrieve_command(self, all=False, raw=False):
+        return self.make_command('certmaprule_show', self.name, all=all,
+                                 raw=raw)
+
+    def check_retrieve(self, result, all=False, raw=False):
+        if all:
+            expected = self.filter_attrs(self.retrieve_all_keys)
+        else:
+            expected = self.filter_attrs(self.retrieve_keys)
+        assert_deepequal(
+            dict(
+                value=self.name,
+                summary=None,
+                result=expected,
+            ),
+            result
+        )
+
+    def make_find_command(self, *args, **kwargs):
+        return self.make_command('certmaprule_find', *args, **kwargs)
+
+    def check_find(self, result, all=False, raw=False):
+        if all:
+            expected = self.filter_attrs(self.retrieve_all_keys)
+        else:
+            expected = self.filter_attrs(self.retrieve_keys)
+        assert_deepequal(
+            dict(
+                count=1,
+                truncated=False,
+                summary=u'1 Certificate Identity Mapping Rule matched',
+                result=[expected],
+            ),
+            result
+        )
+
+    def make_update_command(self, updates):
+        return self.make_command('certmaprule_mod', self.name, **updates)
+
+    def check_update(self, result, extra_keys=()):
+        assert_deepequal(
+            dict(
+                value=self.name,
+                summary=u'Modified Certificate Identity Mapping Rule "{}"'
+                        u''.format(self.name),
+                result=self.filter_attrs(self.update_keys | set(extra_keys)),
+            ),
+            result
+        )
+
+    def make_enable_command(self):
+        return self.make_command('certmaprule_enable', self.name)
+
+    def check_enable(self, result):
+        assert_deepequal(
+            dict(
+                value=self.name,
+                summary=u'Enabled Certificate Identity Mapping Rule "{}"'
+                        u''.format(self.name),
+                result=True,
+            ),
+            result
+        )
+
+    def make_disable_command(self):
+        return self.make_command('certmaprule_disable', self.name)
+
+    def check_disable(self, result):
+        assert_deepequal(
+            dict(
+                value=self.name,
+                summary=u'Disabled Certificate Identity Mapping Rule "{}"'
+                        u''.format(self.name),
+                result=True,
+            ),
+            result
+        )

From 02fd55f4cced9f7200ece29e99959878ba717e93 Mon Sep 17 00:00:00 2001
From: David Kupka <dku...@redhat.com>
Date: Tue, 24 Jan 2017 16:21:54 +0100
Subject: [PATCH 3/3] tests: certmap: Test ACI works as expected

https://fedorahosted.org/freeipa/ticket/6542
---
 ipatests/test_xmlrpc/test_certmap_plugin.py | 265 ++++++++++++++++++++++++++++
 1 file changed, 265 insertions(+)

diff --git a/ipatests/test_xmlrpc/test_certmap_plugin.py b/ipatests/test_xmlrpc/test_certmap_plugin.py
index 9343f9a..fc2b22a 100644
--- a/ipatests/test_xmlrpc/test_certmap_plugin.py
+++ b/ipatests/test_xmlrpc/test_certmap_plugin.py
@@ -2,12 +2,18 @@
 # Copyright (C) 2017  FreeIPA Contributors see COPYING for license
 #
 
+from contextlib import contextmanager
 import itertools
+from nose.tools import assert_raises
 import pytest
 
+from ipalib import api, errors
 from ipapython.dn import DN
 from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
 from ipatests.test_xmlrpc.tracker.certmap_plugin import CertmapruleTracker
+from ipatests.util import assert_deepequal
+from ipatests.util import change_principal, unlock_principal_password
+
 
 certmaprule_create_params = {
         u'cn': u'test_rule',
@@ -40,6 +46,22 @@
     'ipacertmappriority',
 )
 
+CREATE_PERM = u'System: Add Certmap Rules'
+READ_PERM = u'System: Read Certmap Rules'
+UPDATE_PERM = u'System: Modify Certmap Rules'
+DELETE_PERM = u'System: Delete Certmap Rules'
+
+certmaprule_permissions = {
+    u'C': CREATE_PERM,
+    u'R': READ_PERM,
+    u'U': UPDATE_PERM,
+    u'D': DELETE_PERM,
+}
+
+CERTMAP_USER = u'cuser'
+CERTMAP_PASSWD = 'Secret123'
+
+
 def dontfill_idfn(dont_fill):
     return u"dont_fill=({})".format(', '.join([
         u"{}".format(d) for d in dont_fill
@@ -105,3 +127,246 @@ def test_disable(self, certmap_rule):
     def test_enable(self, certmap_rule):
         certmap_rule.ensure_exists()
         certmap_rule.enable()
+
+
+class Result(Exception):
+    def __init__(self, value):
+        self.value = value
+
+
+@contextmanager
+def execute_with_expected(user, password, perms, exps, ok_expected=None):
+    """
+    Run command as specified user. Check exception or return value
+    according provided rules.
+
+    @param user     Change to this user before calling the command
+    @param password User to change user
+    @param perms    User has those permissions
+    @param exps     Iterable containing tuple
+                    (permission, exception_class, expected_result,)
+                    If permission is missing command must raise exception of
+                    exception_class. If exception class is None command must
+                    raise Result(expected_result)
+    @param ok_expected  When no permission is missing command must raise
+                        Result(ok_expected)
+    """
+    with change_principal(user, password):
+        for perm, exception, expected in exps:
+            if perm not in perms:
+                if exception:
+                    with assert_raises(exception):
+                        yield
+                else:
+                    try:
+                        yield
+                    except Result as got:
+                        assert_deepequal(expected, got.value)
+                    else:
+                        if ok_expected:
+                            assert("Command didn't raise Result")
+                break
+        else:
+            try:
+                yield
+            except Result as got:
+                if ok_expected:
+                    assert_deepequal(ok_expected, got.value)
+            else:
+                if ok_expected:
+                    assert("Command didn't raise Result")
+
+
+def permissions_idfn(perms):
+    i = []
+    for short_name, long_name in certmaprule_permissions.items():
+        if long_name in perms:
+            i.append(short_name)
+        else:
+            i.append('-')
+    return ''.join(i)
+
+
+@pytest.fixture(
+    scope='class',
+    params=itertools.chain(*[
+            itertools.combinations(certmaprule_permissions.values(), l)
+            for l in range(len(certmaprule_permissions.values())+1)
+    ]),
+    ids=permissions_idfn,
+)
+def certmap_user_permissions(request):
+    tmp_password = u'Initial123'
+
+    priv_name = u'test_certmap_privilege'
+    role_name = u'test_certmap_role'
+
+    api.Command.user_add(CERTMAP_USER, givenname=u'Certmap', sn=u'User',
+                         userpassword=tmp_password)
+    unlock_principal_password(CERTMAP_USER, tmp_password,
+                              CERTMAP_PASSWD)
+
+    api.Command.privilege_add(priv_name)
+    for perm_name in request.param:
+        api.Command.privilege_add_permission(priv_name, permission=perm_name)
+    api.Command.role_add(role_name)
+    api.Command.role_add_privilege(role_name, privilege=priv_name)
+    api.Command.role_add_member(role_name, user=CERTMAP_USER)
+
+    def finalize():
+        try:
+            api.Command.user_del(CERTMAP_USER)
+        except Exception:
+            pass
+        try:
+            api.Command.role_del(role_name)
+        except Exception:
+            pass
+        try:
+            api.Command.privilege_del(priv_name)
+        except Exception:
+            pass
+    request.addfinalizer(finalize)
+
+    return request.param
+
+
+class TestPermission(XMLRPC_test):
+    def test_create(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_missing()
+
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (CREATE_PERM, errors.ACIError, None,),
+                (READ_PERM, errors.NotFound, None,),
+            ],
+        ):
+            certmap_rule.create()
+
+        # Tracker sets 'exists' to True even when the create does not
+        # succeed so ensure_missing wouldn't be reliable here
+        try:
+            certmap_rule.delete()
+        except Exception:
+            pass
+
+    def test_retrieve(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_exists()
+
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (READ_PERM, errors.NotFound, None,),
+            ],
+        ):
+            certmap_rule.retrieve()
+
+    def test_find(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_exists()
+
+        expected_without_read = {
+            u'count': 0,
+            u'result': (),
+            u'summary': u'0 Certificate Identity Mapping Rules matched',
+            u'truncated': False,
+        }
+        expected_ok = {
+            u'count': 1,
+            u'result': [{
+                k: (v,) for k, v in certmaprule_create_params.items()
+            }],
+            u'summary': u'1 Certificate Identity Mapping Rule matched',
+            u'truncated': False,
+        }
+        expected_ok[u'result'][0][u'dn'] = DN(
+            (u'cn', expected_ok[u'result'][0][u'cn'][0]),
+            api.env.container_certmaprules,
+            api.env.basedn,
+        )
+        expected_ok[u'result'][0][u'ipaenabledflag'] = (u'TRUE',)
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (READ_PERM, None, expected_without_read,),
+            ],
+            expected_ok,
+        ):
+            find = certmap_rule.make_find_command()
+            got = find(**{k: v for k, v in certmaprule_create_params.items()
+                          if k is not u'dn'})
+            raise Result(got)
+
+    def test_update(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_missing()
+        certmap_rule.ensure_exists()
+
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (READ_PERM, errors.NotFound, None,),
+                (UPDATE_PERM, errors.ACIError, None,),
+            ],
+        ):
+            certmap_rule.update(
+                certmaprule_update_params,
+                {o: [v] for o, v in certmaprule_update_params.items()},
+            )
+
+    def test_delete(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_exists()
+
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (DELETE_PERM, errors.ACIError, None,),
+            ],
+        ):
+            certmap_rule.delete()
+
+        # Tracker sets 'exists' to False even when the delete does not
+        # succeed so ensure_missing wouldn't be reliable here
+        try:
+            certmap_rule.delete()
+        except Exception:
+            pass
+
+    def test_enable(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_exists()
+        certmap_rule.disable()
+
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (READ_PERM, errors.NotFound, None,),
+                (UPDATE_PERM, errors.ACIError, None,),
+            ],
+        ):
+            certmap_rule.enable()
+
+    def test_disable(self, certmap_rule, certmap_user_permissions):
+        certmap_rule.ensure_exists()
+        certmap_rule.enable()
+
+        with execute_with_expected(
+            CERTMAP_USER,
+            CERTMAP_PASSWD,
+            certmap_user_permissions,
+            [
+                (READ_PERM, errors.NotFound, None,),
+                (UPDATE_PERM, errors.ACIError, None,),
+            ],
+        ):
+            certmap_rule.disable()
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to