Skip to content

Commit b96470b

Browse files
authored
Simplify controls.json format (#63)
1 parent 3f93e2d commit b96470b

File tree

11 files changed

+217
-30
lines changed

11 files changed

+217
-30
lines changed

CHANGES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
# UNRELEASED
1+
# 1.3.0
22

3+
- [IMPROVED] Simplified `controls.json` format. Original format is also supported.
4+
- [NEW] Added documentation for `controls.json` and check execution.
5+
- [NEW] Added ControlDescriptor unit tests.
36
- [FIXED] ComplianceFetcher session object is auto-closed now in tearDownClass.
47

58
# 1.2.7

compliance/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
# limitations under the License.
1515
"""Compliance automation package."""
1616

17-
__version__ = '1.2.7'
17+
__version__ = '1.3.0'

compliance/controls.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,14 @@ class ControlDescriptor(object):
3030

3131
def __init__(self, dirs=None):
3232
"""Construct and initialize the ControlDescriptor object."""
33-
dirs = dirs or [os.path.abspath('.')]
3433
self._controls = {}
3534
self._paths = []
36-
for d in dirs:
37-
json_file = os.path.join(d, 'controls.json')
35+
for d in dirs or ['.']:
36+
json_file = os.path.join(os.path.abspath(d), 'controls.json')
3837
if not os.path.isfile(json_file):
3938
continue
4039
self._controls.update(json.loads(open(json_file).read()))
41-
self._paths.append(json_file)
40+
self._paths.append(json_file)
4241

4342
@property
4443
def paths(self):
@@ -54,24 +53,30 @@ def as_dict(self):
5453
def accred_checks(self):
5554
"""Provide all checks by accreditation (key) as a dictionary."""
5655
if not hasattr(self, '_accred_checks'):
57-
self._accred_checks = defaultdict(list)
58-
for check, evidence in self._controls.items():
59-
for control in evidence.values():
60-
for accreds in control.values():
61-
for accred in accreds:
62-
self._accred_checks[accred].append(check)
56+
self._accred_checks = defaultdict(set)
57+
for check in self._controls.keys():
58+
accreds = self.get_accreditations(check)
59+
for accred in accreds:
60+
self._accred_checks[accred].add(check)
6361
return self._accred_checks
6462

6563
def get_accreditations(self, test_path):
6664
"""
6765
Provide the accreditation list for a given test_path.
6866
69-
:param test_path: the Python path to the test. For instance:
70-
``package.accr1.TestClass`` or ``package.accr2.test_function``
67+
This works for original and simplified controls formats.
68+
69+
Original: {'test_path': {'key': {'sub-key: ['accred1', 'accred2']}}}
70+
Simplified: {'test_path': ['accred1', 'accred2']}
71+
72+
:param test_path: the Python path to the test.
73+
For example: ``package.category.checks.module.TestClass``
7174
"""
72-
test_paths = self._controls.get(test_path, {})
75+
check_details = self._controls.get(test_path, {})
76+
if isinstance(check_details, list):
77+
return set(check_details)
7378
accreditations = [
74-
itertools.chain(*c.values()) for c in test_paths.values()
79+
itertools.chain(*c.values()) for c in check_details.values()
7580
]
7681
return set(itertools.chain(*accreditations))
7782

doc-source/design-principles.rst

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ The tool is divided in two main parts:
2222
Both fetch and check phases are run by unittest. This is very convenient
2323
as fetchers and checks are loaded automatically by ``unittest``.
2424

25+
2526
Evidences
2627
~~~~~~~~~
2728

@@ -145,7 +146,7 @@ This is a list of modifications that are completely forbidden:
145146
* Adding live-generated data that does not come from the source.
146147

147148
* Applying `check-like` logic (e.g. your data update if it includes an
148-
`if`). Checkers should test the evidence, not fetchers.
149+
`if`). Checks should test the evidence, not fetchers.
149150

150151
Evidence Validation
151152
===================
@@ -231,6 +232,13 @@ due to an unavailable evidence dependency.
231232
...
232233
return json.dumps(foo_bar_data)
233234

235+
Fetcher Execution
236+
=================
237+
238+
The Auditree framework will run all fetchers (tests prefixed by ``fetch_``)
239+
that it can find.
240+
241+
234242
Compliance Checks
235243
~~~~~~~~~~~~~~~~~
236244

@@ -242,8 +250,8 @@ provided on the command line.
242250
Checks *assume* that all evidence is retrieved by fetchers. Consequently
243251
checks **should not** be used to retrieve or store any ``RawEvidence`` in the
244252
evidence locker. Each check class may have from one to multiple checks defined
245-
(that is, a check is a method prefixed with `test_` in a check class). Each of
246-
these checks will be executed by the compliance tool with the following
253+
(that is, a check is a method prefixed with ``test_`` in a check class). Each of
254+
these checks will be executed by the Auditree framework with the following
247255
possible results:
248256

249257
* ``OK``: the check ran successfully and **passed** all validations.
@@ -359,12 +367,34 @@ prior to executing the check's logic.
359367
self.add_warnings('bar stuff', warnings)
360368
self.add_successes('bar stuff', successes)
361369

370+
Check Execution
371+
===============
372+
373+
The Auditree framework executes checks (tests prefixed by ``test_``) based
374+
on accreditation groupings defined in a ``controls.json`` config file.
375+
This is especially useful when targeting check result content to the
376+
appropriate groups of people. The framework will by default look for
377+
``controls.json`` in the current directory. It is possible to supply the
378+
framework with alternate ``controls.json`` location(s) by providing an
379+
alternate path or paths at the end of a compliance check execution command via
380+
the CLI. In the case of multiple locations, the framework will combine the
381+
content of all ``controls.json`` files found together. With this check to
382+
accreditation mapping, the framework can execute checks based on the
383+
accreditations passed to the framework by the CLI.
384+
385+
``controls.json`` content format example::
386+
387+
{
388+
"chk_pkg.chk_cat_foo.checks.chk_module_foo.FooCheckClass": ["accred.one"],
389+
"chk_pkg.chk_cat_bar.checks.chk_module_bar.BarCheckClass": ["accred.one", "accred.two"]
390+
}
391+
362392

363393
Fixers
364394
~~~~~~
365395

366396
After checks have been run, but before notifications or reports are
367-
generated, the compliance tool will optionally try to fix the
397+
generated, the Auditree framework will optionally try to fix the
368398
issues automatically. This is controlled with the ``--fix`` option.
369399
By default it is ``off``, and this is the mode that is used during the
370400
daily CI runs in Travis. But you can also set it to ``dry-run`` or ``on``.
@@ -379,6 +409,7 @@ in the notification message.
379409

380410
See :ref:`fixers` section for more information.
381411

412+
382413
Report Builder
383414
~~~~~~~~~~~~~~
384415

@@ -402,10 +433,11 @@ messages to stdout, etc).
402433

403434
See :ref:`notifiers-description` section for more information.
404435

436+
405437
Execution Config
406438
~~~~~~~~~~~~~~~~
407439

408-
The compliance tool is designed to be run locally from your PC or from
440+
The Auditree framework is designed to be run locally from your PC or from
409441
a CI server like Jenkins or Travis. The execution can be tweaked at 2
410442
levels:
411443

@@ -422,6 +454,7 @@ levels:
422454

423455
.. _credentials:
424456

457+
425458
Credentials
426459
~~~~~~~~~~~
427460

doc-source/quick-start.rst

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ There might be some terms in this quick start that you don't fully
99
understand, so you may want to have a look into
1010
:ref:`design-principles` section.
1111

12-
The compliance tool requires, at least, one directory with the
12+
The Auditree framework requires, at least, one directory with the
1313
fetchers and checks. In order to learn how to use it, let's use a
1414
demo folder with a simple set of fetchers and checks. You can find it
1515
at `doc/demo-checks`::
@@ -59,7 +59,7 @@ mode::
5959

6060
$ compliance --fetch --evidence no-push -C setup.json .
6161

62-
The compliance tool will ``pull`` the repository to
62+
The Auditree framework will ``pull`` the repository to
6363
``/tmp/compliance`` (only if it does not exist already), then run all
6464
the fetchers that need to be run (i.e. those whose evidence TTL
6565
has expired) but it will **not** push anything. This is handy for
@@ -97,10 +97,17 @@ instead::
9797
controls.json
9898
-------------
9999

100-
The mapping between accreditations and checks happens at
101-
``controls.json``. New checks must be included here in order to be
102-
collected by the compliance tool. Note that this is not the same case
103-
as in fetchers, where all of them are executed.
100+
The mapping between a check (check class path) and accreditations
101+
(a list of accreditations) happens in the ``controls.json`` config
102+
file. Each new check must be included in ``controls.json`` in
103+
order to be considered for execution by the Auditree framework.
104+
Note that this is not the case for fetchers, where all are executed.
105+
As an example, the format for ``controls.json`` is as follows::
106+
107+
{
108+
"chk_pkg.chk_cat_foo.checks.chk_module_foo.FooCheckClass": ["accred.one"],
109+
"chk_pkg.chk_cat_bar.checks.chk_module_bar.BarCheckClass": ["accred.one", "accred.two"]
110+
}
104111

105112

106113
A few recommendations

doc-source/report-builder.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Report Builder
66
==============
77

8-
After tests have been run by the compliance tool, the
8+
After tests have been run by the Auditree framework, the
99
:py:class:`~compliance.report.ReportBuilder` is executed in order to
1010
render all the required reports. This is how it works:
1111

@@ -43,7 +43,7 @@ render all the required reports. This is how it works:
4343
notify that the error occurred, in standard output. Note that report
4444
generation will not halt on an error, and will attempt to generate all other
4545
reports.
46-
46+
4747

4848
.. _templating:
4949

doc-source/running-on-travis.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Running on Travis
66
=================
77

8-
Running compliance tool from a CI like Travis can be really useful for
8+
Running the Auditree framework from a CI like Travis can be really useful for
99
executing your compliance checks periodically. Thus you can track the
1010
current level of compliance for different standards and also notify
1111
people whenever there is a failure, so it can be fixed in some way.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"foo_pkg.checks.test_foo_module.FooCheck": {
3+
"foo_evidence": {
4+
"foo_control": ["accred.foo"]
5+
}
6+
}
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"bar_pkg.checks.test_bar_module.BarCheck": ["accred.bar"]}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# -*- mode:python; coding:utf-8 -*-
2+
# Copyright (c) 2020 IBM Corp. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""Compliance automation control descriptor tests module."""

0 commit comments

Comments
 (0)