Source code for compliance.controls

# -*- mode:python; coding:utf-8 -*-
# Copyright (c) 2020 IBM Corp. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Compliance check controls automation module."""

import copy
import itertools
import json
import os
from collections import defaultdict


[docs]class ControlDescriptor(object): """ Class abstraction for controls.json content. Used when processing controls.json content. """ def __init__(self, dirs=None): """Construct and initialize the ControlDescriptor object.""" self._controls = {} self._paths = [] for d in dirs or ['.']: json_file = os.path.join(os.path.abspath(d), 'controls.json') if not os.path.isfile(json_file): continue self._controls.update(json.loads(open(json_file).read())) self._paths.append(json_file) @property def paths(self): """All absolute paths to ``controls.json`` file(s).""" return self._paths @property def as_dict(self): """Provide control descriptor content as a modifiable dictionary.""" return copy.deepcopy(self._controls) @property def accred_checks(self): """Provide all checks by accreditation (key) as a dictionary.""" if not hasattr(self, '_accred_checks'): self._accred_checks = defaultdict(set) for check in self._controls.keys(): accreds = self.get_accreditations(check) for accred in accreds: self._accred_checks[accred].add(check) return self._accred_checks
[docs] def get_accreditations(self, test_path): """ Provide the accreditation list for a given test_path. This works for original and simplified controls formats. Original: {'test_path': {'key': {'sub-key: ['accred1', 'accred2']}}} Simplified: {'test_path': ['accred1', 'accred2']} :param test_path: the Python path to the test. For example: ``package.category.checks.module.TestClass`` """ check_details = self._controls.get(test_path, {}) if isinstance(check_details, list): return set(check_details) accreditations = [ itertools.chain(*c.values()) for c in check_details.values() ] return set(itertools.chain(*accreditations))
[docs] def is_test_included(self, test_path, accreditations): """ Provide boolean result of whether a check is part of accreditations. :param test_path: the Python path to the test. For instance: ``package.accr1.TestClass`` or ``package.accr2.test_function`` :param accreditations: list of accreditations names where ``test_path`` may be included. """ current_accreditations = self.get_accreditations(test_path) matched = set(accreditations).intersection(set(current_accreditations)) return len(matched) != 0