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)
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)
def test_responsible(self): # test "organization" id = "AT-3" c = SecControl(id) self.assertTrue(c.responsible == "organization") id = "AU-8" c = SecControl(id) self.assertTrue(c.responsible == "information system") # test "[Withdrawn" id = "SA-7" c = SecControl("SA-7") self.assertTrue(c.responsible == "withdrawn")
def test_supplemental_guidance(self): id = "AC-16" c = SecControl(id) self.assertTrue( c.supplemental_guidance == "Information is represented internally within information systems using abstractions known as data structures. Internal data structures can represent different types of entities, both active and passive. Active entities, also known as subjects, are typically associated with individuals, devices, or processes acting on behalf of individuals. Passive entities, also known as objects, are typically associated with data structures such as records, buffers, tables, files, inter-process pipes, and communications ports. Security attributes, a form of metadata, are abstractions representing the basic properties or characteristics of active and passive entities with respect to safeguarding information. These attributes may be associated with active entities (i.e., subjects) that have the potential to send or receive information, to cause information to flow among objects, or to change the information system state. These attributes may also be associated with passive entities (i.e., objects) that contain or receive information. The association of security attributes to subjects and objects is referred to as binding and is typically inclusive of setting the attribute value and the attribute type. Security attributes when bound to data/information, enables the enforcement of information security policies for access control and information flow control, either through organizational processes or information system functions or mechanisms. The content or assigned values of security attributes can directly affect the ability of individuals to access organizational information.\nOrganizations can define the types of attributes needed for selected information systems to support missions/business functions. There is potentially a wide range of values that can be assigned to any given security attribute. Release markings could include, for example, US only, NATO, or NOFORN (not releasable to foreign nationals). By specifying permitted attribute ranges and values, organizations can ensure that the security attribute values are meaningful and relevant. The term security labeling refers to the association of security attributes with subjects and objects represented by internal data structures within organizational information systems, to enable information system-based enforcement of information security policies. Security labels include, for example, access authorizations, data life cycle protection (i.e., encryption and data expiration), nationality, affiliation as contractor, and classification of information in accordance with legal and compliance requirements. The term security marking refers to the association of security attributes with objects in a human-readable form, to enable organizational process-based enforcement of information security policies. The AC-16 base control represents the requirement for user-based attribute association (marking). The enhancements to AC-16 represent additional requirements including information system-based attribute association (labeling). Types of attributes include, for example, classification level for objects and clearance (access authorization) level for subjects. An example of a value for both of these attribute types is Top Secret." )
def node_options_by_id(self, node): """ return options for single node id """ # Pass in options to method options = {} sc = SecControl(node) sc_title = sc.title options['label'] = "%s\n%s" % (node, sc_title.title()) options['shape'] = "egg" options['fontname'] = "arial" options['fontsize'] = "12" # options['fontcolor'] = "blue" # tooltip and clickable URL links (svg) options['tooltip'] = "(%s) %s" % (node, sc.title.title()) options['URL'] = "/control?id=%s" % sc.id # color code by responsibility options['fontcolor'] = { 'organization': 'cornflowerblue', 'information system': 'palevioletred', 'withdrawn': 'gray' }[sc.responsible] options['color'] = { 'organization': 'cornflowerblue', 'information system': 'palevioletred', 'withdrawn': 'gray' }[sc.responsible] return options
def test_resolve_control_to_list(self): id = "AU-3" c = SecControl(id) cv = SecControlViz(id) cv.dep_resolve(cv.dep_dict, id, cv.resolved) # print "precursors: ", cv.resolved self.assertTrue(cv.resolved == ['RA-3', 'AU-2', 'AU-3'])
def test_no_existing_control(self): id = "XY-3000" c = SecControl(id) self.assertTrue(c.title == None) self.assertTrue(c.description == None) self.assertTrue(c.supplemental_guidance == None) self.assertTrue(c.responsible == None) self.assertTrue(c.details == {})
def test_details_control_enhancement(self): id = "AU-3 (1)" c = SecControl(id) self.assertTrue(c.title == "ADDITIONAL AUDIT INFORMATION") self.assertTrue( c.description == "The information system generates audit records containing the following additional information: [Assignment: organization-defined additional, more detailed information]." )
def controllist(self, ids="AU-4,AU-6", format="html"): cherrypy.response.headers['Content-Type'] = 'application/json' controllist = [] j = dict() y = dict() # return ids.split(',') for id in ids.split(','): id = id.upper() sc = SecControl(id) if sc.title is None and sc.description is None and format == "html": # control does not exist, return 404 print "\n*** control does not exist" raise cherrypy.HTTPError("404 Not Found", "The requested resource does not exist") controllist.append(sc.get_control_json()) j[id] = sc.get_control_json() y[id] = sc.get_control_yaml() # render yaml if format == "yaml": if sc.title is None and sc.description is None: raise cherrypy.HTTPError("404 Not Found", "The requested resource does not exist") cherrypy.response.headers['Content-Type'] = 'text/yaml' return yaml.safe_dump(y, default_flow_style=False) # render for 18F's control-masonry YAML format with separate subsections if format == "control-masonry": cherrypy.response.headers['Content-Type'] = 'text/yaml' tmpl = env.get_template('control-masonry.yaml') return tmpl.render(controllist=controllist) # render json if format == "json": cherrypy.response.headers['Content-Type'] = 'application/json' if sc.title is None and sc.description is None: raise cherrypy.HTTPError("404 Not Found", "The requested resource does not exist") return json.dumps(controllist) else: # render html cherrypy.response.headers['Content-Type'] = 'text/html' tmpl = env.get_template('controllist.html') return tmpl.render(controllist=controllist)
def node_options(node): options = {} sc = SecControl(node) options['label'] = "%s\n%s" % (node, sc.title) options['shape'] = "box3d" options['fontname'] = "arial" options['fontsize'] = "12" # options['fontcolor'] = "blue" # color code by responsibility options['fontcolor'] = {'organization': 'blue', 'information system': 'red', 'withdrawn': 'gray'}[sc.responsible] options['color'] = {'organization': 'blue', 'information system': 'red', 'withdrawn': 'gray'}[sc.responsible] return options
def dep_resolve(graph, node, resolved): if node in graph: # print node sc = SecControl(node) print "%s - %s (%s)" % (node, sc.title, sc.responsible) # print " edgees: %s" % (graph[node]) for edge in graph[node]: if edge not in resolved: dep_resolve(graph, edge, resolved) resolved.append(node) else: print "%s not found in graph" % (node)
def family(self, id="AC", format="html"): id = id.upper() family_control_count = {"AC": 25, "AU": 16, "AT": 5, "CM": 11, "CP": 13, "IA": 11, "IR": 10, "MA": 6, "MP": 8, "PS": 8, "PE": 20, "PL": 9, "PM": 16, "RA": 6, "CA": 9, "SC": 44, "SI": 17, "SA": 22} families = {"AC": "Access Control", "AU": "Audit and Accountability", "AT": "Awareness and Training", "CM": "Configuration Management", "CP": "Contingency Planning", "IA": "Identification and Authentication", "IR": "Incident Response", "MA": "Maintenance", "MP": "Media Protection", "PS": "Personnel Security", "PE": "Physical and Environmental Protection", "PL": "Planning", "PM": "Program Management", "RA": "Risk Assessment", "CA": "Security Assessment and Authorization", "SC": "System and Communications Protection", "SI": "System and Information Integrity", "SA": "System and Services Acquisition"} control_list = [] for control in range(1,family_control_count[id]+1): sc = SecControl("%s-%d" % (id, control)) control_list.append('<div><a href="/control?id=%s-%d">%s-%d</a> - %s</div>' % (id, control, id, control, sc.title.title())) return """<html> <head> <title>800-53 Controls - {sc_id}</title> <link rel="stylesheet" type="text/css" href="/assets/css/main.css"> </head> <body> <form id="form_lookup" method="get" action="control"> 800-53 control id: <input type="text" value="" name="id" /> <button type="submit">Show me!</button> <a href="/">families</a> </form> <div id="container_index"> <h2>{sc_id} - {sc_family}</h2> <div class="control_list"> {sc_list} </div> </div> </body> </html>""".format(sc_id = id, sc_family = families[id], sc_list = "\n".join(control_list))
def test_id(self): id = "AT-3" c = SecControl(id) self.assertTrue(id == c.id)
def test_get_title(self): id = "CA-5" c = SecControl(id) cv = SecControlViz(id) self.assertTrue("PLAN OF ACTION AND MILESTONES" == c.title)
def control(self, id="AU-4", format="html"): id = id.upper() sc = SecControl(id) if sc.title is None and sc.description is None and format == "html": # control does not exist, return 404 print "\n*** control does not exist" raise cherrypy.HTTPRedirect("/error404") cv = SecControlViz(id) # create graphviz file cv.precursor_list(cv.dep_dict, id, cv.nodes) # create edges for node in cv.nodes: cv.precursor_edges(cv.dep_dict, node, cv.edges) digraph = cv.add_nodes(cv.digraph(), cv.node_options_tuples(cv.nodes)) # print "<%s>" % digraph # determine graph image size node_count = len(cv.nodes) if node_count <= 5: cv.width, cv.height = 2.5, 2.5 if node_count <= 2: cv.width, cv.height = 2.5, 2.5 if node_count >= 6: cv.width, cv.height = 2.75, 2.75 if node_count >= 10: cv.width, cv.height = 3, 3 if node_count >= 20: cv.width, cv.height = 3, 3 if node_count >= 40: cv.width, cv.height = 4, 4 if node_count >= 100: cv.width, cv.height = 12, 10 print "node_count", node_count print "w, h", cv.width, cv.height # weak test, first delete file if exists try: os.remove("output/img/%s-precursors" % id) os.remove("output/img/%s-precursors.%s" % (id, cv.vizformat)) except OSError: pass # generate graphviz file graph_label = "%s Control Chain" % (id) cv.add_edges( cv.add_nodes( cv.digraph( engine="dot", body={'size ="%d,%d";' % (cv.width, cv.height)}, graph_attr={ "label": graph_label, "labelloc": "bottom", "labeljust": "center", "fontcolor": "slategray", "fontname": "Arial", "fontsize": "14", "K": "4.6", }, ), cv.node_options_tuples(cv.nodes), ), cv.edges, ).render("output/img/%s-precursors" % id) # read contents of svg file into variable with open("output/img/%s-precursors.svg" % id, "r") as svg_file: svg_content = svg_file.read() # render json if format == "json": cherrypy.response.headers["Content-Type"] = "application/json" if sc.title is None and sc.description is None: raise cherrypy.HTTPError("404 Not Found", "The requested resource does not exist") return json.dumps(sc.get_control_json()) # render html page return """<html> <head> <title>800-53 Control {sc_id}</title> <link rel="stylesheet" type="text/css" href="/assets/css/main.css"> <style> svg {{ height: {sc_graph_height}; width: 1800px; }} </style> </head> <body> <form id="form_lookup" method="get" action="control"> 800-53 control id: <input type="text" value="" name="id" /> <button type="submit">Show me!</button> <a href="/">families</a> </form> <h2>({sc_id}) {sc_title}</h2> <!-- Graph image by adding svg block into html page --> <!--h4>Control Dependency Chain</h4--> <div id="graph"> {sc_svg} </div> <div id="graphkey"> key: <div style="color: cornflowerblue">blue is organization responsibility</div> <div style="color: palevioletred">light red is information system responsibility</div> </div> <h3>Control Description</h3> <p style="width:800;">{sc_desc}</p> <h3>Supplemental Guidance</h3> <p>{sc_suppl}</p> <h3>Control Enhancements</h3> <p>{sc_enhance}</p> </body> </html>""".format( sc_id=id, sc_title=sc.title, sc_desc=replace_line_breaks( replace_line_breaks(sc.description.encode("utf-8"), "\n", "<br /><br />"), "\t", " ", ), sc_svg=svg_content, sc_graph_height=cv.height * 96, sc_enhance=replace_line_breaks(replace_unicodes(sc.control_enhancements)), sc_suppl=replace_line_breaks(replace_unicodes(sc.supplemental_guidance)), path=os.path.abspath(os.getcwd()), )
# resolved = [] # showEdges(dep_dict, "CA-2") # print " " # resolved = [] # dep_resolve(dep_dict, "CA-2", resolved) # print "Resolve ", "AU-4" # resolved = [] # dep_resolve(dep_dict, "AU-4", resolved) if __name__ == "__main__": while (1==1): control_input = raw_input("Resolve which control? ") if control_input == "q": exit() sc = SecControl(control_input) # print "%s - %s " % (sc.id, sc.title) print "====================================" print sc.id, ": ", dep_dict[sc.id] resolved = [] # dep_resolve(dep_dict, sc.id, resolved) precursor_list(dep_dict, sc.id, resolved) print resolved edges = [] for node in resolved: precursor_edges(dep_dict, node, edges) print edges print " "
def test_details_nonexistent_control(self): id = "AX-3" c = SecControl(id) self.assertTrue(c.title == None)
def control(self, id="AU-4", format="html"): id = id.upper() sc = SecControl(id) if sc.title is None and sc.description is None and format == "html": # control does not exist, return 404 print "\n*** control does not exist" raise cherrypy.HTTPRedirect("/error404") cv = SecControlViz(id) # create graphviz file cv.precursor_list(cv.dep_dict, id, cv.nodes) # create edges for node in cv.nodes: cv.precursor_edges(cv.dep_dict, node, cv.edges) digraph = cv.add_nodes(cv.digraph(), cv.node_options_tuples(cv.nodes)) # print "<%s>" % digraph # determine graph image size node_count = len(cv.nodes) if node_count <= 5: cv.width,cv.height = 2.5,2.5 if node_count <= 2: cv.width,cv.height = 2.5,2.5 if node_count >= 6: cv.width,cv.height = 2.75,2.75 if node_count >= 10: cv.width,cv.height = 3,3 if node_count >= 20: cv.width,cv.height = 3,3 if node_count >= 40: cv.width,cv.height = 4,4 if node_count >= 100: cv.width,cv.height = 12,10 print "node_count", node_count print "w, h", cv.width, cv.height # weak test, first delete file if exists try: os.remove("output/img/%s-precursors" % id) os.remove("output/img/%s-precursors.%s" % (id, cv.vizformat)) except OSError: pass # generate graphviz file graph_label = "%s Control Chain" % (id) cv.add_edges(cv.add_nodes(cv.digraph(engine='dot', body={'size ="%d,%d";' % (cv.width, cv.height)}, graph_attr={'label': graph_label, 'labelloc': 'bottom', 'labeljust': 'center', 'fontcolor':'slategray', 'fontname':'Arial', 'fontsize': '14', 'K': '4.6'}), cv.node_options_tuples(cv.nodes)), cv.edges ).render("output/img/%s-precursors" % id) # read contents of svg file into variable with open("output/img/%s-precursors.svg" % id, "r") as svg_file: svg_content = svg_file.read() # render json if format == "json": cherrypy.response.headers['Content-Type'] = 'application/json' if sc.title is None and sc.description is None: raise cherrypy.HTTPError("404 Not Found", "The requested resource does not exist") return json.dumps(sc.get_control_json()) with open('compliance/system/project_info.yml', 'r') as f: project = yaml.load(f) sc_desc = use_org_name(sc.description.encode('utf-8'), project['organization']['name']) sc_desc = replace_assignments(sc_desc, project) sc_desc = replace_line_breaks(replace_line_breaks(sc_desc, "\n", "<br /><br />"), "\t", " ") # render html page tmpl = env.get_template('control.html', project) return tmpl.render( sc_id = id, sc_title = sc.title, sc_desc = sc_desc, sc_svg = svg_content, sc_graph_height = cv.height*96, path=os.path.abspath(os.getcwd()) )
def test_details(self): id = "AT-3" c = SecControl(id) self.assertTrue(c.title == "ROLE-BASED SECURITY TRAINING")