On 28.07.2011 23:42, Rob Crittenden wrote:
>> Fixed this now and also removed some residual debug prints in unit
>> tests. Patch attached.
>>
> 
> nack
> 
> There is an EXAMPLES section in the help but it just explains the
> options and provides no examples. I think we can just drop the EXAMPLES
> header. Providing examples for this might be rather convoluted, though
> seeing a couple of command-lines might provide enough context.
I decided to add examples.

> It should probably mention that user, srchost, host and service are all
> required but that becomes rather obvious when you try to execute the
> command.
Added this.

> If you provide a single, not found rule to test against a ValueError is
> thrown when validating that the output is valid.
> 
> $ ipa hbactest --user=rcrit --srchost=foo --host=bar --service=baz
> --rules=testnotfound
> 
> ipa: ERROR: non-public: ValueError: hbactest.validate_output(): missing
> keys ['matched', 'notmatched'] in {'error': [u'test22'], 'value':
> u'False', 'summary': u'Unresolved rules in --rules'}
> Traceback (most recent call last):
>   File "/home/rcrit/redhat/freeipa-master/ipaserver/rpcserver.py", line
> 220, in wsgi_execute
>     result = self.Command[name](*args, **options)
>   File "/home/rcrit/redhat/freeipa-master/ipalib/frontend.py", line 436,
> in __call__
>     self.validate_output(ret)
>   File "/home/rcrit/redhat/freeipa-master/ipalib/frontend.py", line 883,
> in validate_output
>     nice, missing, output)
> ValueError: hbactest.validate_output(): missing keys ['matched',
> 'notmatched'] in {'error': [u'test22'], 'value': u'False', 'summary':
> u'Unresolved rules in --rules'}
> ipa: DEBUG: response: InternalError: an internal error has occurred
> 
My bad (two returns taking different paths).

Fixed that all and added unit test for non-existing rules.
Modified description to be more detailed and added real examples.

-- 
/ Alexander Bokovoy
From 74a83a3b9b0f848ab07f88ff2523e82c717f2ba9 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Fri, 22 Jul 2011 16:30:44 +0300
Subject: [PATCH] Add hbactest command.
 https://fedorahosted.org/freeipa/ticket/386

HBAC rules control who can access what services on what hosts and from where.
You can use HBAC to control which users or groups on a source host can
access a service, or group of services, on a target host.

Since applying HBAC rules implies use of a production environment,
this plugin aims to provide simulation of HBAC rules evaluation without
having access to the production environment.

 Test user coming from source host to a service on a named host against
 existing enabled rules.

 ipa hbactest --user= --srchost= --host= --service=
              [--rules=rules-list] [--nodetail] [--enabled] [--disabled]

 --user, --srchost, --host, and --service are mandatory, others are optional.

 If --rules is specified simulate enabling of the specified rules and test
 the login of the user using only these rules.

 If --enabled is specified, all enabled HBAC rules will be added to simulation

 If --disabled is specified, all disabled HBAC rules will be added to simulation

 If --nodetail is specified, do not return information about rules matched/not 
matched.

 If both --rules and --enabled are specified, apply simulation to --rules _and_
 all IPA enabled rules.

 If no --rules specified, simulation is run against all IPA enabled rules.

EXAMPLES:

    1. Use all enabled HBAC rules in IPA database to simulate:
    $ ipa  hbactest --user=a1a --srchost=foo --host=bar --service=ssh
    --------------------
    Access granted: True
    --------------------
      notmatched: my-second-rule
      notmatched: my-third-rule
      notmatched: myrule
      matched: allow_all

    2. Disable detailed summary of how rules were applied:
    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh --nodetail
    --------------------
    Access granted: True
    --------------------

    3. Test explicitly specified HBAC rules:
    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh 
--rules=my-second-rule,myrule
    ---------------------
    Access granted: False
    ---------------------
      notmatched: my-second-rule
      notmatched: myrule

    4. Use all enabled HBAC rules in IPA database + explicitly specified rules:
    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh 
--rules=my-second-rule,myrule --enabled
    --------------------
    Access granted: True
    --------------------
      notmatched: my-second-rule
      notmatched: my-third-rule
      notmatched: myrule
      matched: allow_all

    5. Test all disabled HBAC rules in IPA database:
    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh --disabled
    ---------------------
    Access granted: False
    ---------------------
      notmatched: new-rule

    6. Test all disabled HBAC rules in IPA database + explicitly specified 
rules:
    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh 
--rules=my-second-rule,myrule --disabled
    ---------------------
    Access granted: False
    ---------------------
      notmatched: my-second-rule
      notmatched: my-third-rule
      notmatched: myrule

    7. Test all (enabled and disabled) HBAC rules in IPA database:
    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh --enabled 
--disabled
    --------------------
    Access granted: True
    --------------------
      notmatched: my-second-rule
      notmatched: my-third-rule
      notmatched: myrule
      notmatched: new-rule
      matched: allow_all

Only rules existing in IPA database are tested. They may be in enabled or 
disabled disabled state.
Specifying them through --rules option explicitly enables them only in 
simulation run.
Specifying non-existing rules will not grant access and report non-existing 
rules in output.
---
 API.txt                                   |   15 ++
 VERSION                                   |    2 +-
 freeipa.spec.in                           |    5 +
 ipalib/plugins/hbactest.py                |  330 +++++++++++++++++++++++++++++
 tests/test_xmlrpc/test_hbactest_plugin.py |  206 ++++++++++++++++++
 5 files changed, 557 insertions(+), 1 deletions(-)
 create mode 100644 ipalib/plugins/hbactest.py
 create mode 100644 tests/test_xmlrpc/test_hbactest_plugin.py

diff --git a/API.txt b/API.txt
index 
42a212b1ebda0f8e1f45b016c5ba421f16ffb24c..5c4a7fe93bf6ca3bff86b5b43f9c5e85238353fd
 100644
--- a/API.txt
+++ b/API.txt
@@ -1321,6 +1321,21 @@ option: Str('version?', exclude='webui', 
flags=['no_option', 'no_output'])
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 
'User-friendly description of action performed')
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an 
LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, "The primary_key value of the entry, 
e.g. 'jdoe' for a user")
+command: hbactest
+args: 0,8,5
+option: Str('user', cli_name='user', label=Gettext('User name', domain='ipa', 
localedir=None), primary_key=True)
+option: Str('sourcehost', cli_name='srchost', label=Gettext('Source host', 
domain='ipa', localedir=None))
+option: Str('targethost', cli_name='host', label=Gettext('Target host', 
domain='ipa', localedir=None))
+option: Str('service', cli_name='service', label=Gettext('Service', 
domain='ipa', localedir=None))
+option: List('rules?', cli_name='rules', label=Gettext('Rules to test. If not 
specified, --enabled is assumed', domain='ipa', localedir=None), 
multivalue=True)
+option: Flag('nodetail?', autofill=True, cli_name='nodetail', default=False, 
label=Gettext('Hide details which rules are matched, not matched, or invalid', 
domain='ipa', localedir=None))
+option: Flag('enabled?', autofill=True, cli_name='enabled', default=False, 
label=Gettext('Include all enabled IPA rules into test [default]', 
domain='ipa', localedir=None))
+option: Flag('disabled?', autofill=True, cli_name='disabled', default=False, 
label=Gettext('Include all disabled IPA rules into test', domain='ipa', 
localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 
'User-friendly description of action performed')
+output: Output('matched', (<type 'list'>, <type 'tuple'>, <type 'NoneType'>), 
Gettext('Matched rules', domain='ipa', localedir=None))
+output: Output('notmatched', (<type 'list'>, <type 'tuple'>, <type 
'NoneType'>), Gettext('Not matched rules', domain='ipa', localedir=None))
+output: Output('error', (<type 'list'>, <type 'tuple'>, <type 'NoneType'>), 
Gettext('Non-existent or invalid rules', domain='ipa', localedir=None))
+output: Output('value', <type 'bool'>, Gettext('Result of simulation', 
domain='ipa', localedir=None))
 command: host_add
 args: 1,14,3
 arg: Str('fqdn', validate_host, attribute=True, cli_name='hostname', 
label=Gettext('Host name', domain='ipa', localedir=None), multivalue=False, 
normalizer=<lambda>, primary_key=True, required=True)
diff --git a/VERSION b/VERSION
index 
98e92c5dd3a6902e8552fa81f491fec6e1633c12..0abf5962f983e42cdcef50e65ecdbd06c9a85030
 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=10
+IPA_API_VERSION_MINOR=11
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 
f51677d81f39be3cf8598282fd44caaef6b663d8..42137432b4b810873fb98232c8604bcf1960958d
 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -59,6 +59,7 @@ BuildRequires:  python-kerberos
 BuildRequires:  python-rhsm
 BuildRequires:  pyOpenSSL
 BuildRequires:  pylint
+BuildRequires:  libipa_hbac-python
 
 %description
 IPA is an integrated solution to provide centrally managed Identity (machine,
@@ -201,6 +202,7 @@ Requires: python-netaddr >= 0.7.5-3
 %else
 Requires: python-netaddr
 %endif
+Requires: libipa_hbac-python
 
 Obsoletes: ipa-python >= 1.0
 
@@ -511,6 +513,9 @@ fi
 %ghost %attr(0644,root,apache) %config(noreplace) 
%{_sysconfdir}/ipa/default.conf
 
 %changelog
+* Tue Jul 26 2011 Alexander Bokovoy <aboko...@redhat.com> - 2.0.90-8
+- Add libipa_hbac-python dependency for hbactest plugin
+
 * Wed Jul 20 2011 Rob Crittenden <rcrit...@redhat.com> - 2.0.90-7
 - Make cyrus-sasl-gssapi requires arch-specific
 
diff --git a/ipalib/plugins/hbactest.py b/ipalib/plugins/hbactest.py
new file mode 100644
index 
0000000000000000000000000000000000000000..a7dbb5d6b1d19c3ca6bc36aba0f42f1f510d8316
--- /dev/null
+++ b/ipalib/plugins/hbactest.py
@@ -0,0 +1,330 @@
+# Authors:
+#   Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+Simulate use of Host-based access controls
+
+HBAC rules control who can access what services on what hosts and from where. 
+You can use HBAC to control which users or groups on a source host can
+access a service, or group of services, on a target host.
+
+Since applying HBAC rules implies use of a production environment,
+this plugin aims to provide simulation of HBAC rules evaluation without
+having access to the production environment.
+
+ Test user coming from source host to a service on a named host against
+ existing enabled rules.
+
+ ipa hbactest --user= --srchost= --host= --service=
+              [--rules=rules-list] [--nodetail] [--enabled] [--disabled]
+
+ --user, --srchost, --host, and --service are mandatory, others are optional.
+
+ If --rules is specified simulate enabling of the specified rules and test
+ the login of the user using only these rules.
+
+ If --enabled is specified, all enabled HBAC rules will be added to simulation
+
+ If --disabled is specified, all disabled HBAC rules will be added to 
simulation
+
+ If --nodetail is specified, do not return information about rules matched/not 
matched.
+
+ If both --rules and --enabled are specified, apply simulation to --rules _and_
+ all IPA enabled rules.
+
+ If no --rules specified, simulation is run against all IPA enabled rules.
+
+EXAMPLES:
+
+    1. Use all enabled HBAC rules in IPA database to simulate:
+    $ ipa  hbactest --user=a1a --srchost=foo --host=bar --service=ssh
+    --------------------
+    Access granted: True
+    --------------------
+      notmatched: my-second-rule
+      notmatched: my-third-rule
+      notmatched: myrule
+      matched: allow_all
+    
+    2. Disable detailed summary of how rules were applied:
+    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh --nodetail
+    --------------------
+    Access granted: True
+    --------------------
+    
+    3. Test explicitly specified HBAC rules:
+    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh 
--rules=my-second-rule,myrule
+    ---------------------
+    Access granted: False
+    ---------------------
+      notmatched: my-second-rule
+      notmatched: myrule
+    
+    4. Use all enabled HBAC rules in IPA database + explicitly specified rules:
+    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh 
--rules=my-second-rule,myrule --enabled
+    --------------------
+    Access granted: True
+    --------------------
+      notmatched: my-second-rule
+      notmatched: my-third-rule
+      notmatched: myrule
+      matched: allow_all
+    
+    5. Test all disabled HBAC rules in IPA database:
+    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh --disabled
+    ---------------------
+    Access granted: False
+    ---------------------
+      notmatched: new-rule
+    
+    6. Test all disabled HBAC rules in IPA database + explicitly specified 
rules:
+    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh 
--rules=my-second-rule,myrule --disabled
+    ---------------------
+    Access granted: False
+    ---------------------
+      notmatched: my-second-rule
+      notmatched: my-third-rule
+      notmatched: myrule
+    
+    7. Test all (enabled and disabled) HBAC rules in IPA database:
+    $ ipa hbactest --user=a1a --srchost=foo --host=bar --service=ssh --enabled 
--disabled
+    --------------------
+    Access granted: True
+    --------------------
+      notmatched: my-second-rule
+      notmatched: my-third-rule
+      notmatched: myrule
+      notmatched: new-rule
+      matched: allow_all
+ 
+"""
+
+from ipalib import api, errors, output
+from ipalib import Command, List, Str, Flag
+from types import NoneType
+from ipalib.cli import to_cli
+from ipalib import _, ngettext
+
+try:
+    import pyhbac
+except ImportError as e:
+    print >>sys.stderr, "Could not load the pyhbac module. Make sure 
libipa_hbac-python is available"
+    raise e
+
+def convert_to_ipa_rule(rule):
+    # convert a dict with a rule to an pyhbac rule
+    ipa_rule = pyhbac.HbacRule(rule['cn'][0])
+    ipa_rule.enabled = rule['ipaenabledflag'][0]
+    # Following code attempts to process rule systematically
+    structure = (('user',       'memberuser',    'user',    'group',        
ipa_rule.users),
+         ('host',       'memberhost',    'host',    'hostgroup',    
ipa_rule.targethosts),
+         ('sourcehost', 'sourcehost',    'host',    'hostgroup',    
ipa_rule.srchosts),
+         ('service',    'memberservice', 'hbacsvc', 'hbacsvcgroup', 
ipa_rule.services),
+        )
+    for element in structure:
+        category = '%scategory' % (element[0])
+        if category in rule and rule[category][0] == u'all':
+            # rule applies to all elements
+            element[4].category = set([pyhbac.HBAC_CATEGORY_ALL])
+        else:
+            # rule is about specific entities
+            # Check if there are explicitly listed entities
+            attr_name = '%s_%s' % (element[1], element[2])
+            if attr_name in rule:
+                element[4].names = rule[attr_name]
+            # Now add groups of entities if they are there
+            attr_name = '%s_%s' % (element[1], element[3])
+            if attr_name in rule:
+                element[4].groups = rule[attr_name]
+    return ipa_rule
+
+
+class hbactest(Command):
+
+    has_output = (
+        output.summary,
+        output.Output('matched', (list, tuple, NoneType),   _('Matched 
rules')),
+        output.Output('notmatched', (list, tuple, NoneType), _('Not matched 
rules')),
+        output.Output('error', (list, tuple, NoneType), _('Non-existent or 
invalid rules')),
+        output.Output('value',  bool, _('Result of simulation'), 
['no_display']),
+    )
+
+    takes_options = (
+        Str('user',
+            cli_name='user',
+            label=_('User name'),
+            primary_key=True,
+        ),
+        Str('sourcehost',
+            cli_name='srchost',
+            label=_('Source host'),
+        ),
+        Str('targethost',
+            cli_name='host',
+            label=_('Target host'),
+        ),
+        Str('service',
+            cli_name='service',
+            label=_('Service'),
+        ),
+        List('rules?',
+             cli_name='rules',
+             label=_('Rules to test. If not specified, --enabled is assumed'),
+        ),
+        Flag('nodetail?',
+             cli_name='nodetail',
+             label=_('Hide details which rules are matched, not matched, or 
invalid'),
+        ),
+        Flag('enabled?',
+             cli_name='enabled',
+             label=_('Include all enabled IPA rules into test [default]'),
+        ),
+        Flag('disabled?',
+             cli_name='disabled',
+             label=_('Include all disabled IPA rules into test'),
+        ),
+    )
+
+    def execute(self, *args, **options):
+        # First receive all needed information:
+        # 1. HBAC rules (whether enabled or disabled)
+        # 2. Required options are (user, source host, target host, service)
+        # 3. Options: rules to test (--rules, --enabled, --disabled), request 
for detail output
+        rules = []
+        hbacset = self.api.Command.hbacrule_find()['result']
+
+        # Use all enabled IPA rules by default
+        all_enabled = True
+        all_disabled = False
+
+        # We need a local copy of test rules in order find incorrect ones
+        testrules = {}
+        if 'rules' in options:
+            testrules = list(options['rules'])
+            # When explicit rules are provided, disable assumptions
+            all_enabled = False
+            all_disabled = False
+
+        # Check if --disabled is specified, include all disabled IPA rules
+        if options['disabled']:
+            all_disabled = True
+            all_enabled = False
+
+        # Finally, if enabled is specified implicitly, override above decisions
+        if options['enabled']:
+            all_enabled = True
+
+        # We have some rules, import them
+        # --enabled will import all enabled rules (default)
+        # --disabled will import all disabled rules
+        # --rules will implicitly add the rules from a rule list
+        for rule in hbacset:
+            ipa_rule = convert_to_ipa_rule(rule)
+            if ipa_rule.name in testrules:
+                ipa_rule.enabled = True
+                rules.append(ipa_rule)
+                testrules.remove(ipa_rule.name)
+            elif all_enabled and ipa_rule.enabled:
+                # Option --enabled forces to include all enabled IPA rules 
into test
+                rules.append(ipa_rule)
+            elif all_disabled and not ipa_rule.enabled:
+                # Option --disabled forces to include all disabled IPA rules 
into test
+                ipa_rule.enabled = True
+                rules.append(ipa_rule)
+
+        # Check if there are unresolved rules left
+        if len(testrules) > 0:
+            # Error, unresolved rules are left in --rules
+            return {'summary' : unicode(_(u'Unresolved rules in --rules')),
+                    'error': testrules, 'matched': None, 'notmatched': None,
+                    'value' : False}
+
+        # Rules are converted to pyhbac format, we can test them
+        request = pyhbac.HbacRequest()
+        request.user.name = options['user']
+        request.service.name = options['service']
+        request.srchost.name = options['sourcehost']
+        request.targethost.name = options['targethost']
+
+        matched_rules = []
+        notmatched_rules = []
+        error_rules = []
+
+        result = {'matched':None, 'notmatched':None, 'error':None}
+        if not options['nodetail']:
+            # Validate runs rules one-by-one and reports failed ones
+            for ipa_rule in rules:
+                try:
+                    res = request.evaluate([ipa_rule])
+                    if res == pyhbac.HBAC_EVAL_ALLOW:
+                        matched_rules.append(ipa_rule.name)
+                    if res == pyhbac.HBAC_EVAL_DENY:
+                        notmatched_rules.append(ipa_rule.name)
+                except pyhbac.HbacError as (code, rule_name):
+                    if code == pyhbac.HBAC_EVAL_ERROR:
+                        error_rules.append(rule_name)
+                        self.log.info('Native IPA HBAC rule "%s" parsing 
error: %s' % \
+                                      (rule_name, 
pyhbac.hbac_result_string(code)))
+                except (TypeError, IOError) as (info):
+                    self.log.error('Native IPA HBAC module error: %s' % (info))
+
+            access_granted = len(matched_rules) > 0
+        else:
+            res = request.evaluate(rules)
+            access_granted = (res == pyhbac.HBAC_EVAL_ALLOW)
+
+        result['summary'] = _('Access granted: %s') % (access_granted)
+
+        
+        if len(matched_rules) > 0:
+            result['matched'] = matched_rules
+        if len(notmatched_rules) > 0:
+            result['notmatched'] = notmatched_rules
+        if len(error_rules) > 0:
+            result['error'] = error_rules
+
+        result['value'] = access_granted
+        return result
+
+    def output_for_cli(self, textui, output, *args, **options):
+        """
+        Command.output_for_cli() uses --all option to decide whether to print 
detailed output.
+        We use --detail to allow that, thus we need to redefine 
output_for_cli().
+        """
+        # Note that we don't actually use --detail below to see if details 
need 
+        # to be printed as our execute() method will return None for 
corresponding 
+        # entries and None entries will be skipped.
+        for o in self.output:
+            outp = self.output[o]
+            if 'no_display' in outp.flags:
+                continue
+            result = output[o]
+            if isinstance(result, (list, tuple)):
+                    textui.print_attribute(outp.name, result, '%s: %s', 1, 
True)
+            elif isinstance(result, (unicode, bool)):
+                if o == 'summary':
+                    textui.print_summary(result)
+                else:
+                    textui.print_indented(result)
+
+        # Propagate integer value for result. It will give proper command line 
result for scripts
+        return int(not bool(output['value']))
+
+api.register(hbactest)
+
+
diff --git a/tests/test_xmlrpc/test_hbactest_plugin.py 
b/tests/test_xmlrpc/test_hbactest_plugin.py
new file mode 100644
index 
0000000000000000000000000000000000000000..e5926f526710d20cea938cefa5ec79c243569e3c
--- /dev/null
+++ b/tests/test_xmlrpc/test_hbactest_plugin.py
@@ -0,0 +1,206 @@
+# Authors:
+#   Pavel Zuna <pz...@redhat.com>
+#   Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2009-2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+Test the `ipalib/plugins/hbactest.py` module.
+"""
+
+from xmlrpc_test import XMLRPC_test, assert_attr_equal
+from ipalib import api
+from ipalib import errors
+from types import NoneType
+
+# Test strategy:
+# 1. Create few allow rules: with user categories, with explicit users, with 
user groups, with groups, with services
+# 2. Create users for test
+# 3. Run detailed and non-detailed tests for explicitly specified rules, check 
expected result
+#
+class test_hbactest(XMLRPC_test):
+    """
+    Test the `hbactest` plugin.
+    """
+    rule_names = [u'testing_rule1234_%d' % (d) for d in [1,2,3,4]]
+    rule_type = u'allow'
+    rule_service = u'ssh'
+    rule_descs = [u'description %d' % (d) for d in [1,2,3,4]]
+
+    test_user = u'hbacrule_test_user'
+    test_group = u'hbacrule_test_group'
+    test_host = u'hbacrule._test_host'
+    test_hostgroup = u'hbacrule_test_hostgroup'
+    test_sourcehost = u'hbacrule._test_src_host'
+    test_sourcehostgroup = u'hbacrule_test_src_hostgroup'
+    test_service = u'ssh'
+
+    def test_0_hbactest_addrules(self):
+        """
+        Prepare data by adding test HBAC rules using `xmlrpc.hbacrule_add'.
+        """
+
+        self.failsafe_add(api.Object.user,
+            self.test_user, givenname=u'first', sn=u'last'
+        )
+        self.failsafe_add(api.Object.group,
+            self.test_group, description=u'description'
+        )
+        self.failsafe_add(api.Object.host,
+            self.test_host, force=True
+        )
+        self.failsafe_add(api.Object.hostgroup,
+            self.test_hostgroup, description=u'description'
+        )
+        self.failsafe_add(api.Object.host,
+            self.test_sourcehost, force=True
+        )
+        self.failsafe_add(api.Object.hostgroup,
+            self.test_sourcehostgroup, description=u'desc'
+        )
+        self.failsafe_add(api.Object.hbacsvc,
+            self.test_service, description=u'desc', force=True
+        )
+
+        for i in [0,1,2,3]:
+            api.Command['hbacrule_add'](
+                self.rule_names[i], accessruletype=self.rule_type, 
description=self.rule_descs[i],
+            )
+
+            ret = api.Command['hbacrule_add_user'](
+                self.rule_names[i], user=self.test_user, group=self.test_group
+            )
+
+            ret = api.Command['hbacrule_add_host'](
+                self.rule_names[i], host=self.test_host, 
hostgroup=self.test_hostgroup
+            )
+
+            ret = api.Command['hbacrule_add_sourcehost'](
+                self.rule_names[i], host=self.test_sourcehost, 
hostgroup=self.test_sourcehostgroup
+            )
+
+            ret = api.Command['hbacrule_add_service'](
+                self.rule_names[i], hbacsvc=self.test_service
+            )
+
+            if i & 1:
+                ret = api.Command['hbacrule_disable'](self.rule_names[i])
+
+    def test_a_hbactest_check_rules_detail(self):
+        """
+        Test 'ipa hbactest --rules' (explicit IPA rules, detailed output)
+        """
+        ret = api.Command['hbactest'](
+            user=self.test_user,
+            sourcehost=self.test_sourcehost,
+            targethost=self.test_host,
+            service=self.test_service,
+            rules=self.rule_names
+        )
+        assert ret['value'] == True
+        assert type(ret['error']) == NoneType
+        for i in [0,1,2,3]:
+            assert self.rule_names[i] in ret['matched']
+
+    def test_b_hbactest_check_rules_nodetail(self):
+        """
+        Test 'ipa hbactest --rules --nodetail' (explicit IPA rules, no 
detailed output)
+        """
+        ret = api.Command['hbactest'](
+            user=self.test_user,
+            sourcehost=self.test_sourcehost,
+            targethost=self.test_host,
+            service=self.test_service,
+            rules=self.rule_names,
+            nodetail=True
+        )
+        assert ret['value'] == True
+        assert ret['error'] == None
+        assert ret['matched'] == None
+        assert ret['notmatched'] == None
+
+    def test_c_hbactest_check_rules_enabled_detail(self):
+        """
+        Test 'ipa hbactest --enabled' (all enabled IPA rules, detailed output)
+        """
+        ret = api.Command['hbactest'](
+            user=self.test_user,
+            sourcehost=self.test_sourcehost,
+            targethost=self.test_host,
+            service=self.test_service,
+            enabled=True
+        )
+        # --enabled will try to work with _all_ enabled rules in IPA database
+        # It means we could have matched something else (unlikely but possible)
+        # Thus, check that our two enabled rules are in matched, nothing more
+        for i in [0,2]:
+            assert self.rule_names[i] in ret['matched']
+
+    def test_d_hbactest_check_rules_disabled_detail(self):
+        """
+        Test 'ipa hbactest --disabled' (all disabled IPA rules, detailed 
output)
+        """
+        ret = api.Command['hbactest'](
+            user=self.test_user,
+            sourcehost=self.test_sourcehost,
+            targethost=self.test_host,
+            service=self.test_service,
+            disabled=True
+        )
+        # --disabled will try to work with _all_ disabled rules in IPA database
+        # It means we could have matched something else (unlikely but possible)
+        # Thus, check that our two disabled rules are in matched, nothing more
+        for i in [1,3]:
+            assert self.rule_names[i] in ret['matched']
+
+    def test_e_hbactest_check_non_existing_rule_detail(self):
+        """
+        Test running 'ipa hbactest' with non-existing rule in --rules
+        """
+        ret = api.Command['hbactest'](
+            user=self.test_user,
+            sourcehost=self.test_sourcehost,
+            targethost=self.test_host,
+            service=self.test_service,
+            rules=[u'%s_1x1' % (rule) for rule in self.rule_names],
+            nodetail=True
+        )
+ 
+        assert ret['value'] == False
+        assert ret['matched'] == None
+        assert ret['notmatched'] == None
+        for rule in self.rule_names:
+            assert u'%s_1x1' % (rule) in ret['error']
+
+    def test_d_hbactest_clear_testing_data(self):
+        """
+        Clear data for HBAC test plugin testing.
+        """
+        for i in [0,1,2,3]:
+            api.Command['hbacrule_remove_host'](self.rule_names[i], 
host=self.test_host)
+            api.Command['hbacrule_remove_host'](self.rule_names[i], 
hostgroup=self.test_hostgroup)
+            api.Command['hbacrule_remove_sourcehost'](self.rule_names[i], 
host=self.test_sourcehost)
+            api.Command['hbacrule_remove_sourcehost'](self.rule_names[i], 
hostgroup=self.test_sourcehostgroup)
+            api.Command['hbacrule_del'](self.rule_names[i])
+
+        api.Command['user_del'](self.test_user)
+        api.Command['group_del'](self.test_group)
+        api.Command['host_del'](self.test_host)
+        api.Command['hostgroup_del'](self.test_hostgroup)
+        api.Command['host_del'](self.test_sourcehost)
+        api.Command['hostgroup_del'](self.test_sourcehostgroup)
+        api.Command['hbacsvc_del'](self.test_service)
+
-- 
1.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to