From 723cc9f301b00659cb5db01d1bd8c69af52a1cf2 Mon Sep 17 00:00:00 2001 From: Greg Elin Date: Fri, 30 Oct 2015 20:23:58 -0400 Subject: [PATCH] Generate JSON, YAML, Control-Masonry format with SecControl.format() method --- README.md | 80 ++++++++++++++++++++++++++ compliancelib/seccontrol.py | 49 ++++++++++++---- compliancelib/tests/test_seccontrol.py | 25 +++++--- setup.py | 2 +- 4 files changed, 135 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a759641..5aa9b85 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,88 @@ personnel can supplement automated malicious code detection and protection tools organizations.\n' >>> c.related_controls 'AT-2,AT-4,PL-4,PS-7,SA-3,SA-12,SA-16' + +>>> c.format('json') +{'description': 'The organization provides role-based security training to personnel with assigned security roles and responsibilities:\na. Before authorizing access to the information system or performing assigned duties;\nb. When required by information system changes; and\nc. [Assignment: organization-defined frequency] thereafter.', 'title': 'ROLE-BASED SECURITY TRAINING', 'responsible': 'organization', 'supplemental_guidance': 'Organizations determine the appropriate content of security training based on the assigned roles and responsibilities of individuals and the specific security requirements of organizations and the information systems to which personnel have authorized access. In addition, organizations provide enterprise architects, information system developers, software developers, acquisition/procurement officials, information system managers, system/network administrators, personnel conducting configuration management and auditing activities, personnel performing independent verification and validation activities, security control assessors, and other personnel having access to system-level software, adequate security-related technical training specifically tailored for their assigned duties. Comprehensive role-based training addresses management, operational, and technical roles and responsibilities covering physical, personnel, and technical safeguards and countermeasures. Such training can include for example, policies, procedures, tools, and artifacts for the organizational security roles defined. Organizations also provide the training necessary for individuals to carry out their responsibilities related to operations and supply chain security within the context of organizational information security programs. Role-based security training also applies to contractors providing services to federal agencies.', 'id': 'AT-3', 'description_intro': 'The organization provides role-based security training to personnel with assigned security roles and responsibilities:', 'description_sections': ['a. Before authorizing access to the information system or performing assigned duties;', 'b. When required by information system changes; and', 'c. [Assignment: organization-defined frequency] thereafter.']} +>>> print(c.format('yaml')) +description: 'The organization provides role-based security training to personnel + with assigned security roles and responsibilities: + + a. Before authorizing access to the information system or performing assigned + duties; + + b. When required by information system changes; and + + c. [Assignment: organization-defined frequency] thereafter.' +description_intro: 'The organization provides role-based security training to personnel + with assigned security roles and responsibilities:' +description_sections: +- a. Before authorizing access to the information system or performing assigned duties; +- b. When required by information system changes; and +- 'c. [Assignment: organization-defined frequency] thereafter.' +id: AT-3 +responsible: organization +supplemental_guidance: Organizations determine the appropriate content of security + training based on the assigned roles and responsibilities of individuals and the + specific security requirements of organizations and the information systems to + which personnel have authorized access. In addition, organizations provide enterprise + architects, information system developers, software developers, acquisition/procurement + officials, information system managers, system/network administrators, personnel + conducting configuration management and auditing activities, personnel performing + independent verification and validation activities, security control assessors, + and other personnel having access to system-level software, adequate security-related + technical training specifically tailored for their assigned duties. Comprehensive + role-based training addresses management, operational, and technical roles and + responsibilities covering physical, personnel, and technical safeguards and countermeasures. + Such training can include for example, policies, procedures, tools, and artifacts + for the organizational security roles defined. Organizations also provide the + training necessary for individuals to carry out their responsibilities related + to operations and supply chain security within the context of organizational information + security programs. Role-based security training also applies to contractors providing + services to federal agencies. +title: ROLE-BASED SECURITY TRAINING + +>>> print(c.format('control-masonry')) +description: The organization provides role-based security training to personnel with + assigned security roles and responsibilities: a. Before authorizing access + to the information system or performing assigned duties; b. When required by information + system changes; and c. [Assignment: organization-defined frequency] thereafter. +description_intro: The organization provides role-based security training to personnel + with assigned security roles and responsibilities: +description_sections: +- a. Before authorizing access to the information system or performing assigned duties; +- b. When required by information system changes; and +- c. [Assignment: organization-defined frequency] thereafter. +id: AT-3 +name: ROLE-BASED SECURITY TRAINING +``` + +Example code for generating list of controls in `YAML` format + +```python +controllist = ["AT-3", "AU-1", "IR-2"] +d = dict() +for id in controllist: + c = compliancelib.SecControl(id) + d[id] = yaml.load(c.format('yaml')) + +print(yaml.safe_dump(d, default_flow_style=False, encoding='utf-8', allow_unicode=True, explicit_start=True, explicit_end=True)) ``` +Example code for generating list of controls in `control-masonry` format + +```python +controllist = ["AT-3", "AU-1", "IR-2"] +d = dict() +for id in controllist: + c = compliancelib.SecControl(id) + d[id] = yaml.load(c.format('control-masonry')) + +print(yaml.safe_dump(d, default_flow_style=False, encoding='utf-8', allow_unicode=True, explicit_start=True, explicit_end=True)) + +``` + + To see control dependencies, simply do in python shell:: ``` diff --git a/compliancelib/seccontrol.py b/compliancelib/seccontrol.py index 5499460..a879b7d 100644 --- a/compliancelib/seccontrol.py +++ b/compliancelib/seccontrol.py @@ -24,6 +24,7 @@ import subprocess import re import xml.etree.ElementTree as ET +import sys def getstatusoutput(cmd): """Return (status, output) of executing cmd in a shell.""" @@ -49,6 +50,7 @@ def __init__(self, id): self._load_control_from_xml() # split description self.set_description_sections() + self._get_control_json() def _load_control_from_xml(self): "load control detail from 800-53 xml using a pure python process" @@ -139,7 +141,17 @@ def _get_responsible(self): else: return "other" - def get_control_json(self): + def format(self, format): + if (format.lower() == "json"): + return self._get_control_json() + if (format.lower() == "yaml"): + return self._get_control_yaml() + if (format.lower() == "control-masonry" or format.lower() == "control_masonry"): + return self._get_control_control_masonry() + # control format is not defined + return False + + def _get_control_json(self): "produce json version of control detail" self.json = {} self.json['id'] = self.id @@ -152,18 +164,31 @@ def get_control_json(self): return self.json # To Do: needs test - def get_control_yaml(self): + def _get_control_yaml(self): "produce yaml version of control detail" - sc_yaml = dict( - id = self.id, - title = self.title, - description = self.description, - description_intro = self.description_intro, - description_sections = self.description_sections, - responsible = self.responsible, - supplemental_guidance = self.supplemental_guidance - ) - return yaml.safe_dump(sc_yaml, default_flow_style=False) + return yaml.safe_dump(self.json, allow_unicode=True, default_flow_style=False, line_break="\n", + indent=4, explicit_start=False, explicit_end=False,) + + def _get_control_control_masonry(self): + "produce control masonry yaml version of control detail" + # get json version + c = self._get_control_json() + # replace ":" with ":" + description_sections = [] + for section in self.description_sections: + description_sections.append(section.replace(":", ":")) + c['description_sections'] = description_sections + c['description'] = self.description.replace(":", ":").replace("\n", " ") + c['description_intro'] = self.description_intro.replace(":", ":") + # add 'name' key + c['name'] = self.title + # remove unnecessary keys + c.pop("title", None) + # c.pop("id", None) + c.pop("responsible", None) + c.pop("supplemental_guidance", None) + return yaml.safe_dump(c, allow_unicode=True, default_flow_style=False, line_break="\n", + indent=4, explicit_start=False, explicit_end=False,) # utility functions def set_description_sections(self): diff --git a/compliancelib/tests/test_seccontrol.py b/compliancelib/tests/test_seccontrol.py index 4fc1fda..aca128a 100644 --- a/compliancelib/tests/test_seccontrol.py +++ b/compliancelib/tests/test_seccontrol.py @@ -74,7 +74,7 @@ def test_generate_json(self): # To do - this test does not work id = "AT-3" c = SecControl(id) - c_json = c.get_control_json() + c_json = c.format('json') # print c_json self.assertTrue(c_json["id"] == c.id) self.assertTrue(c_json["title"] == c.title) @@ -88,16 +88,25 @@ def test_generate_yaml(self): # To do - this test does not work id = "AT-3" c = SecControl(id) - c_yaml = yaml.load(c.get_control_yaml()) - # print c_yaml - self.assertTrue(c_yaml["id"] == c.id) - self.assertTrue(c_yaml["title"] == c.title) - self.assertTrue(c_yaml["description"] == c.description) - self.assertTrue(c_yaml["responsible"] == c.responsible) - self.assertTrue(c_yaml["supplemental_guidance"] == c.supplemental_guidance) + self.assertTrue(c.format('yaml')[0:1] == "AT") + + c_yaml = c.format('yaml') + print c_yaml + # self.assertTrue(c_yaml[c.id]["id"] == c.id) + self.assertTrue(c_yaml[c.id]["title"] == c.title) + self.assertTrue(c_yaml[c.id]["description"] == c.description) + self.assertTrue(c_yaml[c.id]["responsible"] == c.responsible) + self.assertTrue(c_yaml[c.id]["supplemental_guidance"] == c.supplemental_guidance) # test for other (not organization, information system, or [Withdrawn) + def test_generate_control_masonry(self): + id = "AT-3" + c = SecControl(id) + c_cm = c.format('control-masonry') + self.assertTrue(c_cm["name"] == "ROLE-BASED SECURITY TRAINING") + self.assertTrue(c_cm["description"] == "The organization provides role-based security training to personnel with assigned security roles and responsibilities: a. Before authorizing access to the information system or performing assigned duties; b. When required by information system changes; and c. [Assignment: organization-defined frequency] thereafter.") + if __name__ == "__main__": unittest.main() diff --git a/setup.py b/setup.py index e530c1e..cdbe0e0 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ def readme(): return f.read() setup(name='compliancelib', - version='0.5.0', + version='0.6.0', description='A python library of IT Compliance Standards', long_description=readme(), classifiers=[