From 4a9a8b4878695baf4d086463d96442b58b1864f0 Mon Sep 17 00:00:00 2001 From: "Michael DeMichillie (First Information Technology)" Date: Thu, 23 Apr 2020 12:55:38 -0700 Subject: [PATCH 01/10] added needed functions for FITS base SSP --- cis_generator.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cis_generator.py b/cis_generator.py index 90713c5..9f8bd2f 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -70,7 +70,7 @@ def get_customer_responsibility_text(control_text): cust_resp = '' split_text = control_text.split('\n') for text_part in split_text: - if text_part == 'Customer Responsibility:': + if 'Customer Responsibility:' in text_part: continue if ':' in text_part and "Part" in text_part and "http" not in text_part: return cust_resp @@ -154,6 +154,11 @@ def main(docs, cis_workbook, out_file): else: crm_addendum_list = None + cis_controls = [convert_cis_control_number(cis_worksheet.cell(row=x, column = 2).value) for x in range(4, 424)] + for control in [control for control in security_plan if control.number not in cis_controls]: + new_row = [''] * 15 + new_row[1] = control.number + cis_worksheet.append(new_row) fill_cis_worksheet(cis_control_dict, cis_worksheet) fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list) if addendum: From e18615d4b52782dffe26b40e8e68caba7e14f050 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Thu, 19 Aug 2021 09:31:24 -0700 Subject: [PATCH 02/10] update for pipenv and new CIS template --- .gitignore | 3 ++- cis_generator.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 876cd93..64686bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.docx *.doc *.xlsx -*.json \ No newline at end of file +*.json +Pipfile* \ No newline at end of file diff --git a/cis_generator.py b/cis_generator.py index 9f8bd2f..8c3f1a7 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -140,8 +140,8 @@ def append_addendum_controls_to_cis(control_list, cis_worksheet): # for control in control_list: def main(docs, cis_workbook, out_file): - cis_worksheet = cis_workbook['CIS'] - crm_worksheet = cis_workbook['Customer Responsibility Matrix'] + cis_worksheet = cis_workbook['CIS Worksheet'] + crm_worksheet = cis_workbook['CRM Worksheet'] security_plan, addendum = docs crm_control_list = [] cis_control_dict = {} From d0ff1b5a2f9aa23e968f7fac63055549aeb363eb Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Fri, 20 Aug 2021 15:26:12 -0700 Subject: [PATCH 03/10] works with new template --- cis_generator.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cis_generator.py b/cis_generator.py index 8c3f1a7..0f90983 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -1,4 +1,5 @@ import argparse +from pdb import set_trace from ssp import SSP from openpyxl import load_workbook @@ -86,8 +87,8 @@ def get_customer_responsibility_text(control_text): def fill_cis_worksheet(cis_dict, worksheet): for row in worksheet.rows: - if row[0].row > 3 and row[1].value is not None: - control = row[1].value + if row[0].row > 3 and row[0].value is not None: + control = row[0].value control = convert_cis_control_number(control) try: control_object = cis_dict[control] @@ -154,11 +155,12 @@ def main(docs, cis_workbook, out_file): else: crm_addendum_list = None - cis_controls = [convert_cis_control_number(cis_worksheet.cell(row=x, column = 2).value) for x in range(4, 424)] + cis_controls = [convert_cis_control_number(cis_worksheet.cell(row=x, column = 1).value) for x in range(4, 424)] for control in [control for control in security_plan if control.number not in cis_controls]: new_row = [''] * 15 new_row[1] = control.number cis_worksheet.append(new_row) + set_trace() fill_cis_worksheet(cis_control_dict, cis_worksheet) fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list) if addendum: @@ -170,9 +172,10 @@ def fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list): row_counter = 4 ref_counter = 1 for control in crm_control_list: - crm_worksheet.cell(row_counter, 1).value = ref_counter - crm_worksheet.cell(row_counter, 2).value = control.text - crm_worksheet.cell(row_counter, 3).value = control.number + #crm_worksheet.cell(row_counter, 1).value = ref_counter + crm_worksheet.cell(row_counter, 1).value = control.number + crm_worksheet.cell(row_counter, 2).value = 'Yes' + crm_worksheet.cell(row_counter, 3).value = control.text row_counter += 1 ref_counter += 1 if crm_addendum_list: From 653569b0e5a45e24c7efba81be18f9c4d73cf122 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Fri, 20 Aug 2021 15:44:29 -0700 Subject: [PATCH 04/10] remove set_trace --- cis_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cis_generator.py b/cis_generator.py index 0f90983..ac016c7 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -160,7 +160,6 @@ def main(docs, cis_workbook, out_file): new_row = [''] * 15 new_row[1] = control.number cis_worksheet.append(new_row) - set_trace() fill_cis_worksheet(cis_control_dict, cis_worksheet) fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list) if addendum: From fce4901466d8179b1b9b20cb0798fbba293e47b8 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Fri, 20 Aug 2021 16:07:46 -0700 Subject: [PATCH 05/10] part stripping from the new template --- cis_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cis_generator.py b/cis_generator.py index ac016c7..b282ef4 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -187,7 +187,7 @@ def fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list): def convert_cis_control_number(control_number): - control_number = control_number.replace('-0', '-').replace('(0', '(') + control_number = control_number.replace('-0', '-').replace('(0', '(').split(' ', 1)[0] return control_number From 6163753f4f681ce6db6c0cde7446b20bbfee04c9 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Fri, 20 Aug 2021 16:11:51 -0700 Subject: [PATCH 06/10] remove pdb import --- cis_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cis_generator.py b/cis_generator.py index b282ef4..02a9764 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -1,5 +1,4 @@ import argparse -from pdb import set_trace from ssp import SSP from openpyxl import load_workbook From cde563a42eba17955722cdea823bd2a9c356f520 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Mon, 23 Aug 2021 11:08:05 -0700 Subject: [PATCH 07/10] fix for templates with lots of formatting --- cis_generator.py | 65 +++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/cis_generator.py b/cis_generator.py index 02a9764..1095de1 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -1,4 +1,5 @@ -import argparse +import argparse, pdb, re +from string import ascii_letters from ssp import SSP from openpyxl import load_workbook @@ -82,21 +83,32 @@ def get_customer_responsibility_text(control_text): else: return None +def get_max_row(worksheet): + row = 4 + value = worksheet.cell(row, 1).value + while value is not None: + row+=1 + value = worksheet.cell(row, 1).value + return row def fill_cis_worksheet(cis_dict, worksheet): - for row in worksheet.rows: - if row[0].row > 3 and row[0].value is not None: - control = row[0].value - control = convert_cis_control_number(control) - try: - control_object = cis_dict[control] - except KeyError: - print('Could not find entry for control ' + control) - continue - columns = control_object.get_columns() - for column in columns: - row[column].value = 'X' + rownumber = 4 + max_row = get_max_row(worksheet) + while rownumber < max_row: + row = worksheet[rownumber] + control = row[0].value + control = convert_cis_control_number(control) + try: + control_object = cis_dict[control] + except KeyError: + print('Could not find entry for control ' + control) + rownumber += 1 + continue + columns = control_object.get_columns() + for column in columns: + row[column].value = 'X' + rownumber += 1 def create_addendum_controls(addendum): crm_addendum_list = [] @@ -154,7 +166,7 @@ def main(docs, cis_workbook, out_file): else: crm_addendum_list = None - cis_controls = [convert_cis_control_number(cis_worksheet.cell(row=x, column = 1).value) for x in range(4, 424)] + cis_controls = [convert_cis_control_number(cis_worksheet.cell(row=x, column = 1).value) for x in range(4, get_max_row(cis_worksheet))] for control in [control for control in security_plan if control.number not in cis_controls]: new_row = [''] * 15 new_row[1] = control.number @@ -167,22 +179,29 @@ def main(docs, cis_workbook, out_file): cis_workbook.save(out_file) def fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list): - row_counter = 4 - ref_counter = 1 + crm_worksheet_dict = {} + for row in range(4, get_max_row(crm_worksheet)): + cisnumber = crm_worksheet.cell(row, 1).value + if cisnumber is None: + continue + if any(ascii in cisnumber for ascii in ascii_letters): + cisnumber = re.sub(r' (?=\([a-z]\))', '', cisnumber) + if '0' in cisnumber: + cisnumber = re.sub(r'0(?=[1-9])', '', cisnumber) + crm_worksheet_dict[cisnumber] = row for control in crm_control_list: + row_counter = crm_worksheet_dict[control.number] #crm_worksheet.cell(row_counter, 1).value = ref_counter crm_worksheet.cell(row_counter, 1).value = control.number crm_worksheet.cell(row_counter, 2).value = 'Yes' crm_worksheet.cell(row_counter, 3).value = control.text - row_counter += 1 - ref_counter += 1 if crm_addendum_list: for control in crm_addendum_list: - crm_worksheet.cell(row_counter, 1).value = ref_counter - crm_worksheet.cell(row_counter, 2).value = control.text - crm_worksheet.cell(row_counter, 3).value = control.number - row_counter += 1 - ref_counter += 1 + row_counter = crm_worksheet_dict[control.number] + #crm_worksheet.cell(row_counter, 1).value = ref_counter + crm_worksheet.cell(row_counter, 1).value = control.number + crm_worksheet.cell(row_counter, 2).value = 'Yes' + crm_worksheet.cell(row_counter, 3).value = control.text def convert_cis_control_number(control_number): From c40e6d6226b469a3afba181f36a295608d5b4704 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Mon, 23 Aug 2021 11:10:00 -0700 Subject: [PATCH 08/10] remove pdb also special function for max row to account for formatting-only cells --- cis_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cis_generator.py b/cis_generator.py index 1095de1..67822ad 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -1,4 +1,4 @@ -import argparse, pdb, re +import argparse, re from string import ascii_letters from ssp import SSP from openpyxl import load_workbook From 0bca1384577e0943d37b90c77cca85a83dacc8f2 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Tue, 2 Nov 2021 10:13:49 -0700 Subject: [PATCH 09/10] openpyxl increments from zero when using 'row' --- cis_generator.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/cis_generator.py b/cis_generator.py index 67822ad..6141f34 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -1,20 +1,20 @@ -import argparse, re +import argparse, re, pdb from string import ascii_letters from ssp import SSP from openpyxl import load_workbook class CIS_Control: - implementation_columns = {'Implemented': 2, 'Partially Implemented': 3, 'Planned': 4, 'Alternative Implementation': 5, 'Not Applicable': 6} + implementation_columns = {'Implemented': 1, 'Partially Implemented': 2, 'Planned': 3, 'Alternative Implementation': 4, 'Not Applicable': 5} origination_columns = { - 'Service Provider Corporate': 7, - 'Service Provider System Specific': 8, - 'Service Provider Hybrid': 9, - 'Configured by Customer': 10, - 'Provided by Customer': 11, - 'Shared': 12, - 'Inherited': 13, - 'Not Applicable': 14 + 'Service Provider Corporate': 6, + 'Service Provider System Specific': 7, + 'Service Provider Hybrid': 8, + 'Configured by Customer': 9, + 'Provided by Customer': 10, + 'Shared': 11, + 'Inherited': 12, + 'Not Applicable': 13 } def __init__(self, control_object): @@ -70,7 +70,11 @@ def get_customer_responsibility_text(control_text): if "Customer Responsibility" in control_text: cust_resp = '' split_text = control_text.split('\n') - for text_part in split_text: + try: + customer_index = split_text.index('Customer Responsibility:') + except ValueError: + customer_index = split_text.index('Customer Responsibility') + for text_part in split_text[customer_index:]: if 'Customer Responsibility:' in text_part: continue if ':' in text_part and "Part" in text_part and "http" not in text_part: @@ -182,6 +186,7 @@ def fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list): crm_worksheet_dict = {} for row in range(4, get_max_row(crm_worksheet)): cisnumber = crm_worksheet.cell(row, 1).value + crm_worksheet.cell(row=row, column=2).value = "Yes" if cisnumber is None: continue if any(ascii in cisnumber for ascii in ascii_letters): @@ -193,7 +198,7 @@ def fill_crm_worksheet(crm_control_list, crm_worksheet, crm_addendum_list): row_counter = crm_worksheet_dict[control.number] #crm_worksheet.cell(row_counter, 1).value = ref_counter crm_worksheet.cell(row_counter, 1).value = control.number - crm_worksheet.cell(row_counter, 2).value = 'Yes' + crm_worksheet.cell(row_counter, 2).value = 'No' crm_worksheet.cell(row_counter, 3).value = control.text if crm_addendum_list: for control in crm_addendum_list: From 3ac0d90f2c1eff147fba1d7079453aa754f192a6 Mon Sep 17 00:00:00 2001 From: Michael DeMichillie Date: Thu, 18 Nov 2021 13:14:36 -0800 Subject: [PATCH 10/10] Fixed handling of Customer Responsibility colon --- cis_generator.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cis_generator.py b/cis_generator.py index 6141f34..caebed9 100644 --- a/cis_generator.py +++ b/cis_generator.py @@ -70,12 +70,11 @@ def get_customer_responsibility_text(control_text): if "Customer Responsibility" in control_text: cust_resp = '' split_text = control_text.split('\n') - try: - customer_index = split_text.index('Customer Responsibility:') - except ValueError: - customer_index = split_text.index('Customer Responsibility') + for text in split_text: + if "Customer Resp" in text: + customer_index = split_text.index(text) for text_part in split_text[customer_index:]: - if 'Customer Responsibility:' in text_part: + if 'Customer Responsibility' in text_part: continue if ':' in text_part and "Part" in text_part and "http" not in text_part: return cust_resp