From 9a49b94c6027dbe1ab5a9e22e2e81a101af64b55 Mon Sep 17 00:00:00 2001 From: Gildas NOEL Date: Mon, 6 May 2024 13:55:23 +0200 Subject: [PATCH 1/5] =?UTF-8?q?"agents=20mena=C3=A7ants"=C2=A0en=20lieu=20?= =?UTF-8?q?et=20place=20de=20agents=20de=20menace"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/messages/fr.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/messages/fr.json b/frontend/messages/fr.json index a3c80d89e..4bb2d8506 100644 --- a/frontend/messages/fr.json +++ b/frontend/messages/fr.json @@ -247,7 +247,7 @@ "confirmNewPassword": "Confirmer le nouveau mot de passe", "label": "Label", "NA": "N/A", - "threatAgentFactors": "Facteurs liés aux agents de menace", + "threatAgentFactors": "Facteurs liés aux agents menaçants", "vulnerabilityFactors": "Facteurs de vulnérabilité", "businessImpactFactors": "Facteurs d’impact sur les entreprises", "technicalImpactFactors": "Facteurs d’impact techniques", @@ -258,11 +258,11 @@ "skillLevelChoice3": "Utilisateur informatique avancé", "skillLevelChoice4": "Compétences en réseau et en programmation", "skillLevelChoice5": "Compétences en matière de pénétration de la sécurité", - "motiveText": "Dans quelle mesure ce groupe d’agents de menace est-il motivé à trouver et à exploiter cette vulnérabilité ?", + "motiveText": "Dans quelle mesure ce groupe d’agents menaçants est-il motivé à trouver et à exploiter cette vulnérabilité ?", "motiveChoice1": "Récompense faible ou inexistante", "motiveChoice2": "Récompense possible", "motiveChoice3": "Récompense élevée", - "opportunityText": "Quelles ressources et opportunités sont nécessaires pour que ce groupe d’agents de menace trouve et exploite cette vulnérabilité ?", + "opportunityText": "Quelles ressources et opportunités sont nécessaires pour que ce groupe d’agents menaçants trouve et exploite cette vulnérabilité ?", "opportunityChoice1": "Accès complet ou ressources coûteuses requises", "opportunityChoice2": "Accès spécialisé ou ressources requises", "opportunityChoice3": "Certains accès ou ressources requis", From 637cdc95b333777d39beaf21df8900922e3ac947 Mon Sep 17 00:00:00 2001 From: Gildas NOEL Date: Mon, 6 May 2024 15:52:54 +0200 Subject: [PATCH 2/5] Typo --- frontend/messages/fr.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/messages/fr.json b/frontend/messages/fr.json index 4bb2d8506..6636c596e 100644 --- a/frontend/messages/fr.json +++ b/frontend/messages/fr.json @@ -120,7 +120,7 @@ "revokedAt": "Révoqué le", "submitted": "Soumis", "rejected": "Rejeté", - "revoked": "Revoqué", + "revoked": "Révoqué", "locale": "Locale", "defaultLocale": "Locale par défaut", "annotation": "Annotation", @@ -178,7 +178,7 @@ "authors": "Auteurs", "reviewers": "Relecteurs", "processButton": "Traiter", - "selectTargets": "Selectionnez vos cibles", + "selectTargets": "Sélectionnez vos cibles", "composerDescription": "Cela vous aidera à agréger plusieurs composants (projets) pour obtenir une vue d'ensemble de vos risques. Ceci est particulièrement utile pour deux cas d'utilisation", "composerDescription1": "une approche de veille stratégique pour se concentrer sur un sous-ensemble spécifique à travers différents domaines de projet (par exemple, à travers les divisions)", "composerDescription2": "vous êtes intéressé par l'évaluation des risques d'un système spécifique, pour lequel vous avez besoin de l'évaluation des risques des composants sous-jacents", @@ -492,7 +492,7 @@ "mediumSOK": "La force des connaissances à l’appui de l’évaluation est moyenne", "highSOK": "La force des connaissances à l’appui de l’évaluation est élevée", "libraryImportError": "Une erreur a été détectée durant l'importation de votre librairie.", - "libraryAlreadyImportedError": "Cette libairie a été déjà été importée.", + "libraryAlreadyImportedError": "Cette librairie a été déjà été importée.", "invalidLibraryFileError": "Fichier de bibliothèque invalide. Veuillez vérifier le format du fichier.", "taintedFormMessage": "Voulez-vous vraiment quitter cette page ? Toutes les données non enregistrées seront perdues.", "riskScenariosStatus": "Statut des scénarios de risque", From 3e2a943283d907534d1389b5fae9ad80700a0d04 Mon Sep 17 00:00:00 2001 From: Gildas NOEL Date: Mon, 6 May 2024 16:28:54 +0200 Subject: [PATCH 3/5] Folder -> Domain & Typos --- frontend/messages/en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index a6fc37911..e73e612d5 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -94,7 +94,7 @@ "residualLevel": "Residual level", "riskMatrix": "Risk matrix", "project": "Project", - "folder": "Folder", + "folder": "Domain", "riskAssessment": "Risk assessment", "threat": "Threat", "framework": "Framework", @@ -338,7 +338,7 @@ "librariesStore": "Libraries store", "currentlyNoImportedLibraries": "You currently have no imported libraries", "loadingLibraryUploadButton": "Loading the library upload button", - "errorOccuredWhileLoadingLibrary": "The following error occured while loading the library form", + "errorOccuredWhileLoadingLibrary": "The following error occurred while loading the library form", "packager": "Packager", "dependencies": "Dependencies", "copyright": "Copyright", @@ -491,7 +491,7 @@ "lowSOK": "The strength of the knowledge supporting the assessment is low", "mediumSOK": "The strength of the knowledge supporting the assessment is medium", "highSOK": "The strength of the knowledge supporting the assessment is high", - "libraryImportError": "An error occured during the importation of your library.", + "libraryImportError": "An error occurred during the importation of your library.", "libraryAlreadyImportedError": "This library has already been imported.", "invalidLibraryFileError": "Invalid library file. Please make sure the format is correct.", "taintedFormMessage": "Do you want to leave this page? Changes you made may not be saved.", From cde031620ae31e6b6e8441d4f4e128351ab439eb Mon Sep 17 00:00:00 2001 From: eric-intuitem <71850047+eric-intuitem@users.noreply.github.com> Date: Sat, 4 May 2024 01:21:32 +0200 Subject: [PATCH 4/5] matrix converter from Excel to yaml Add colors for probability and impact, even if not yet implemented. risk matrix generation from excel Rename tool, use argparse for better evolutivity Update readme files Add requirements.txt Add 5x5 sensitive matrix Add color column, this is clearer, and allows to declare colors for all objects This will have to be implemented in the frontend for probability and impact (currently it uses incorrectly the color of the risk with same id) --- README.md | 4 +- .../libraries/risk-matrix-3x3-mult.yaml | 88 +++++++ .../libraries/risk-matrix-5x5-sensitive.yaml | 104 ++++++++ tools/README.md | 62 +++-- tools/aircyber/aircyber.py | 4 +- tools/ccm/convert_ccm.py | 10 +- tools/cis/convert_cis.py | 24 +- ...onvert_framework.py => convert_library.py} | 239 ++++++++++++++++-- .../matrix/3x3-mult/risk-matrix-3x3-mult.xlsx | Bin 0 -> 11337 bytes .../risk-matrix-5x5-sensitive.xlsx | Bin 0 -> 12496 bytes tools/requirements.txt | 2 + tools/tisax/convert_tisax.py | 25 +- 12 files changed, 503 insertions(+), 59 deletions(-) create mode 100644 backend/library/libraries/risk-matrix-3x3-mult.yaml create mode 100644 backend/library/libraries/risk-matrix-5x5-sensitive.yaml rename tools/{convert_framework.py => convert_library.py} (65%) create mode 100644 tools/matrix/3x3-mult/risk-matrix-3x3-mult.xlsx create mode 100644 tools/matrix/5x5-sensitive/risk-matrix-5x5-sensitive.xlsx create mode 100644 tools/requirements.txt diff --git a/README.md b/README.md index dff9d7fdd..7113c590c 100644 --- a/README.md +++ b/README.md @@ -129,9 +129,9 @@ Checkout the [library](/backend/library/libraries/) and [tools](/tools/) for the - UK Cyber Essentials - and much more: just ask on [Discord](https://discord.gg/qvkaMdQ8da). If it's an open standard, we'll do it for you, _free of charge_ 😉 -### Add your own framework +### Add your own library (framework, threat catalog, reference controls catalog or matrix) -Have a look in the tools directory and its dedicated readme. The convert_framework.py script will help you create your library from a simple Excel file. A typical framework can be ingested in a few hours. +Have a look in the tools directory and its dedicated readme. The convert_library.py script will help you create your library from a simple Excel file. A typical framework can be ingested in a few hours. You will also find some specific converters in the tools directory (e.g. for CIS or CCM Controls). diff --git a/backend/library/libraries/risk-matrix-3x3-mult.yaml b/backend/library/libraries/risk-matrix-3x3-mult.yaml new file mode 100644 index 000000000..d0d7fb7c6 --- /dev/null +++ b/backend/library/libraries/risk-matrix-3x3-mult.yaml @@ -0,0 +1,88 @@ +urn: urn:intuitem:risk:library:risk-matrix-3x3-mult +locale: fr +ref_id: risk-matrix-3x3-mult +name: Matrice 3x3 multiplicative +description: Matrice de risque simple 3x3 multiplicative +copyright: domaine public +version: 1 +provider: intuitem +packager: intuitem +objects: + risk_matrix: + - urn: urn:intuitem:risk:matrix:3x3-mult + ref_id: risk-matrix-3x3-mult + name: Matrice 3x3 multiplicative + description: Matrice de risque simple 3x3 multiplicative + probability: + - id: 0 + abbreviation: 1 + name: '[1] peu probable' + description: 0-33% + hexcolor: '#92D050' + - id: 1 + abbreviation: 2 + name: '[2] moyennement probable' + description: 34-66% + hexcolor: '#FFFF00' + - id: 2 + abbreviation: 3 + name: "[3] tr\xE8s probable" + description: '>66%' + hexcolor: '#FF0000' + impact: + - id: 0 + abbreviation: 1 + name: '[1] mineur' + description: impact mineur + hexcolor: '#92D050' + - id: 1 + abbreviation: 2 + name: "[2] mod\xE9r\xE9" + description: "impact mod\xE9r\xE9" + hexcolor: '#FFFF00' + - id: 2 + abbreviation: 3 + name: '[3] majeur' + description: impact majeur + hexcolor: '#FF0000' + risk: + - id: 0 + abbreviation: 1 + name: '[1] faible' + description: "n\xE9gligeable" + hexcolor: '#92D050' + - id: 1 + abbreviation: 2 + name: '[2] moyen' + description: "tol\xE9rable" + hexcolor: '#D3FF4E' + - id: 2 + abbreviation: 3 + name: '[3] moyen' + description: "tol\xE9rable" + hexcolor: '#EAFF03' + - id: 3 + abbreviation: 4 + name: '[4] moyen' + description: "tol\xE9rable" + hexcolor: '#FFFF00' + - id: 4 + abbreviation: 6 + name: '[6] fort' + description: "rem\xE9diation sour 6 mois" + hexcolor: '#FFC000' + - id: 5 + abbreviation: 9 + name: '[9] critique' + description: "Rem\xE9diation sous 2 mois" + hexcolor: '#FF0000' + grid: + - - 0 + - 1 + - 2 + - - 1 + - 3 + - 4 + - - 2 + - 4 + - 5 diff --git a/backend/library/libraries/risk-matrix-5x5-sensitive.yaml b/backend/library/libraries/risk-matrix-5x5-sensitive.yaml new file mode 100644 index 000000000..e4ec0b12e --- /dev/null +++ b/backend/library/libraries/risk-matrix-5x5-sensitive.yaml @@ -0,0 +1,104 @@ +urn: urn:intuitem:risk:library:risk-matrix-5x5-sensitive +locale: en +ref_id: risk-matrix-5x5-sensitive +name: 5x5 sensitive +description: 5x5 matrix for highly sensitive +copyright: domaine public +version: 1 +provider: intuitem +packager: intuitem +objects: + risk_matrix: + - urn: urn:intuitem:risk:matrix:5x5-sensitive + ref_id: risk-matrix-5x5-sensitive + name: 5x5 sensitive + description: 5x5 matrix for highly sensitive + probability: + - id: 0 + abbreviation: AC + name: rare + description: rare + - id: 1 + abbreviation: LI + name: unlikely + description: unlikely + - id: 2 + abbreviation: MO + name: moderate + description: moderate + - id: 3 + abbreviation: UN + name: likely + description: likely + - id: 4 + abbreviation: RA + name: almost certain + description: almost certain + impact: + - id: 0 + abbreviation: IN + name: insignificant + description: insignificant + - id: 1 + abbreviation: MI + name: minor + description: minor + - id: 2 + abbreviation: SI + name: significant + description: significant + - id: 3 + abbreviation: MA + name: major + description: major + - id: 4 + abbreviation: SE + name: severe + description: severe + risk: + - id: 0 + abbreviation: LO + name: low + description: low + hexcolor: '#02A45A' + - id: 1 + abbreviation: ME + name: medium + description: medium + hexcolor: '#FFCE02' + - id: 2 + abbreviation: HI + name: high + description: high + hexcolor: '#FFA600' + - id: 3 + abbreviation: CR + name: critical + description: critical + hexcolor: '#FF1A00' + grid: + - - 0 + - 0 + - 0 + - 1 + - 1 + - - 0 + - 0 + - 1 + - 1 + - 2 + - - 0 + - 1 + - 1 + - 2 + - 3 + - - 1 + - 1 + - 2 + - 3 + - 3 + - - 1 + - 2 + - 3 + - 3 + - 3 diff --git a/tools/README.md b/tools/README.md index fbaf89b7a..301fae23b 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,6 +1,6 @@ # Library workbench -The convert-framework.py script can be used to transform an Excel file to a CISO Assistant library. +The convert-library.py script can be used to transform an Excel file to a CISO Assistant library. Have a look to the given examples. @@ -9,7 +9,7 @@ Have a look to the given examples. To launch it, open a shell in a command line, and type: ```bash -python convert-framework.py your_library_file.xlsx +python convert-library.py your_library_file.xlsx ``` This will produce a file name your_library_file.yaml @@ -20,26 +20,34 @@ This will produce a file name your_library_file.yaml Conventions: | means a cell separation, <> means empty cell The first tab shall be named "library_content" and contain the description of the library in the other tabs - library_urn | - library_version | - library_locale | - library_ref_id | - library_name | - library_description | - library_copyright | - library_provider | - library_packager | - library_dependencies | - framework_ref_id | - framework_name | - framework_description | - reference_control_base_urn | | id - threat_base_urn | | id - tab | | requirements | - tab | | threats | - tab | | reference_controls | - + library_urn | + library_version | + library_locale | + library_ref_id | + library_name | + library_description | + library_copyright | + library_provider | + library_packager | + library_dependencies | + framework_ref_id | + framework_name | + framework_description | + framework_min_score | + framework_max_score | + reference_control_base_urn | | id + threat_base_urn | | id + risk_matrix_urn | + risk_matrix_ref_id | + risk_matrix_name | + risk_matrix_description | + tab | | requirements + tab | | threats | + tab | | reference_controls | + tab | | scores + tab | | implementation_groups + tab | | risk_matrix For requirements: If no section_name is given, no upper group is defined, else an upper group (depth 0) with the section name is used. @@ -64,6 +72,16 @@ Conventions: - description - category (policy/process/techncial/physical). - annotation + For risk matrices: + The first line is a header, with the following mandatory fields: + - type: probability/impact/risk. + - id: a number from 0 to n-1 (depending of the number of objects for a given type) + - abbreviation: the abbreviation for the object + - name: name of the object + - description: description of the object + - grid: several columns describing the matrix with colors. + The grid shall be aligned with the probability objects, the columns being the impact in order of id, and the content of each cell being the id of the risk. + This is a topological representation. The display on the screen (transposition, direction of axes) will be managed in the frontend, not in the data model. A library has a single locale. Translated libraries have the same urns, they are merged during import. Dependencies are given as a comma or blank separated list of urns. ``` diff --git a/tools/aircyber/aircyber.py b/tools/aircyber/aircyber.py index 72d3ad944..54fdabdfb 100644 --- a/tools/aircyber/aircyber.py +++ b/tools/aircyber/aircyber.py @@ -95,7 +95,9 @@ ws.append(["tab", "implementation_groups", "implementation_groups"]) ws1 = wb_output.create_sheet("controls") -ws1.append(["assessable", "depth", "ref_id", "name", "description", "implementation_groups"]) +ws1.append( + ["assessable", "depth", "ref_id", "name", "description", "implementation_groups"] +) for row in output_table: ws1.append(row) ws2 = wb_output.create_sheet("implementation_groups") diff --git a/tools/ccm/convert_ccm.py b/tools/ccm/convert_ccm.py index f27204481..0974ea84c 100644 --- a/tools/ccm/convert_ccm.py +++ b/tools/ccm/convert_ccm.py @@ -97,12 +97,18 @@ def pretify_content(content): ws1 = wb_output.create_sheet("controls") ws1.append( ["assessable", "depth", "ref_id", "name", "description", "implementation_groups"] - ) +) for row in output_table: ws1.append(row) ws2 = wb_output.create_sheet("implementation_groups") ws2.append(["ref_id", "name", "description"]) -ws2.append(["lite", "foundational", "foundational controls that should be implemented by any organization, regardless of their budget, maturity and risk profile"]) +ws2.append( + [ + "lite", + "foundational", + "foundational controls that should be implemented by any organization, regardless of their budget, maturity and risk profile", + ] +) ws2.append(["full", "systematic ", "systematic assessment of a cloud implementation"]) print("generate ", output_file_name) wb_output.save(output_file_name) diff --git a/tools/cis/convert_cis.py b/tools/cis/convert_cis.py index 945a10e89..458993cbb 100644 --- a/tools/cis/convert_cis.py +++ b/tools/cis/convert_cis.py @@ -44,7 +44,9 @@ else: safeguard_index += 1 safeguard = f"{control},{safeguard_index}" - implementation_groups = "IG1,IG2,IG3" if ig1 else "IG2,IG3" if ig2 else "IG3" + implementation_groups = ( + "IG1,IG2,IG3" if ig1 else "IG2,IG3" if ig2 else "IG3" + ) output_table.append( ("x", 2, safeguard, title, description, implementation_groups) ) @@ -73,14 +75,28 @@ ws.append(["tab", "implementation_groups", "implementation_groups"]) ws1 = wb_output.create_sheet("controls") -ws1.append(["assessable", "depth", "ref_id", "name", "description", "implementation_groups"]) +ws1.append( + ["assessable", "depth", "ref_id", "name", "description", "implementation_groups"] +) for row in output_table: ws1.append(row) ws2 = wb_output.create_sheet("implementation_groups") ws2.append(["ref_id", "name", "description"]) -ws2.append(["IG1", "Essential Cyber Hygiene", "Minimum standard of information security for all enterprises."]) -ws2.append(["IG2", "", "For enterprises managing IT infrastructure of multiple departments with differing risk profiles."]) +ws2.append( + [ + "IG1", + "Essential Cyber Hygiene", + "Minimum standard of information security for all enterprises.", + ] +) +ws2.append( + [ + "IG2", + "", + "For enterprises managing IT infrastructure of multiple departments with differing risk profiles.", + ] +) ws2.append(["IG3", "", "To secure sensitive and confidential data."]) print("generate ", output_file_name) diff --git a/tools/convert_framework.py b/tools/convert_library.py similarity index 65% rename from tools/convert_framework.py rename to tools/convert_library.py index a64a1c901..7d593169b 100644 --- a/tools/convert_framework.py +++ b/tools/convert_library.py @@ -1,5 +1,5 @@ """ -simple script to transform an Excel file to a yaml library for a CISO assistant framework +simple script to transform an Excel file to a yaml library for CISO assistant Conventions: | means a cell separation, <> means empty cell The first tab shall be named "library_content" and contain the description of the library in the other tabs @@ -21,12 +21,16 @@ framework_max_score | reference_control_base_urn | | id threat_base_urn | | id + risk_matrix_urn | + risk_matrix_ref_id | + risk_matrix_name | + risk_matrix_description | tab | | requirements tab | | threats | tab | | reference_controls | tab | | scores tab | | implementation_groups - tab | | matrix + tab | | risk_matrix For requirements: If no section_name is given, no upper group is defined, else an upper group (depth 0) with the section name is used. @@ -51,12 +55,23 @@ - description - category (policy/process/techncial/physical). - annotation + For risk matrices: + The first line is a header, with the following mandatory fields: + - type: probability/impact/risk. + - id: a number from 0 to n-1 (depending of the number of objects for a given type) + - color: empty cells with the desired color. Can be left with no fill. + - abbreviation: the abbreviation for the object + - name: name of the object + - description: description of the object + - grid: several columns describing the matrix with colors. The colors shall be consistent with the color column. + The grid shall be aligned with the probability objects, the columns being the impact in order of id, and the content of each cell being the id of the risk. + This is a topological representation. The display on the screen (transposition, direction of axes) will be managed in the frontend, not in the data model. A library has a single locale. Translated libraries have the same urns, they are merged during import. Dependencies are given as a comma or blank separated list of urns. """ import openpyxl -import sys +import argparse import re import yaml from pprint import pprint @@ -81,6 +96,10 @@ "reference_control_base_urn", "threat_base_urn", "library_dependencies", + "risk_matrix_urn", + "risk_matrix_ref_id", + "risk_matrix_name", + "risk_matrix_description", "tab", ) library_vars = {} @@ -89,23 +108,28 @@ library_vars_dict_arg = defaultdict(dict) urn_unicity_checker = set() -if len(sys.argv) <= 1: - print("missing input file parameter") - exit() -input_file_name = sys.argv[1] -ref_name = re.sub(r"\.\w+$", "", input_file_name).lower() + +parser = argparse.ArgumentParser( + prog="convert-library.py", + description="convert an Excel file in a library for CISO Assistant", +) +parser.add_argument("input_file_name") +args = parser.parse_args() + +ref_name = re.sub(r"\.\w+$", "", args.input_file_name).lower() output_file_name = ref_name + ".yaml" -print("parsing", input_file_name) +print("parsing", args.input_file_name) # Define variable to load the dataframe -dataframe = openpyxl.load_workbook(input_file_name) +dataframe = openpyxl.load_workbook(args.input_file_name) requirement_nodes = [] reference_controls = [] threats = [] scores_definition = [] implementation_groups_definition = [] +risk_matrix = {} def error(message): @@ -123,11 +147,118 @@ def read_header(row): return header +# https://gist.github.com/Mike-Honey/b36e651e9a7f1d2e1d60ce1c63b9b633 +from colorsys import rgb_to_hls, hls_to_rgb + +RGBMAX = 0xFF # Corresponds to 255 +HLSMAX = 240 # MS excel's tint function expects that HLS is base 240. see: +# https://social.msdn.microsoft.com/Forums/en-US/e9d8c136-6d62-4098-9b1b-dac786149f43/excel-color-tint-algorithm-incorrect?forum=os_binaryfile#d3c2ac95-52e0-476b-86f1-e2a697f24969 + + +def rgb_to_ms_hls(red, green=None, blue=None): + """Converts rgb values in range (0,1) or a hex string of the form '[#aa]rrggbb' to HLSMAX based HLS, (alpha values are ignored)""" + if green is None: + if isinstance(red, str): + if len(red) > 6: + red = red[-6:] # Ignore preceding '#' and alpha values + blue = int(red[4:], 16) / RGBMAX + green = int(red[2:4], 16) / RGBMAX + red = int(red[0:2], 16) / RGBMAX + else: + red, green, blue = red + h, l, s = rgb_to_hls(red, green, blue) + return (int(round(h * HLSMAX)), int(round(l * HLSMAX)), int(round(s * HLSMAX))) + + +def ms_hls_to_rgb(hue, lightness=None, saturation=None): + """Converts HLSMAX based HLS values to rgb values in the range (0,1)""" + if lightness is None: + hue, lightness, saturation = hue + return hls_to_rgb(hue / HLSMAX, lightness / HLSMAX, saturation / HLSMAX) + + +def rgb_to_hex(red, green=None, blue=None): + """Converts (0,1) based RGB values to a hex string 'rrggbb'""" + if green is None: + red, green, blue = red + return ( + "%02x%02x%02x" + % ( + int(round(red * RGBMAX)), + int(round(green * RGBMAX)), + int(round(blue * RGBMAX)), + ) + ).upper() + + +def get_theme_colors(wb): + """Gets theme colors from the workbook""" + # see: https://groups.google.com/forum/#!topic/openpyxl-users/I0k3TfqNLrc + from openpyxl.xml.functions import QName, fromstring + + xlmns = "http://schemas.openxmlformats.org/drawingml/2006/main" + root = fromstring(wb.loaded_theme) + themeEl = root.find(QName(xlmns, "themeElements").text) + colorSchemes = themeEl.findall(QName(xlmns, "clrScheme").text) + firstColorScheme = colorSchemes[0] + + colors = [] + + for c in [ + "lt1", + "dk1", + "lt2", + "dk2", + "accent1", + "accent2", + "accent3", + "accent4", + "accent5", + "accent6", + ]: + accent = firstColorScheme.find(QName(xlmns, c).text) + for i in list(accent): # walk all child nodes, rather than assuming [0] + if "window" in i.attrib["val"]: + colors.append(i.attrib["lastClr"]) + else: + colors.append(i.attrib["val"]) + + return colors + + +def tint_luminance(tint, lum): + """Tints a HLSMAX based luminance""" + # See: http://ciintelligence.blogspot.co.uk/2012/02/converting-excel-theme-color-and-tint.html + if tint < 0: + return int(round(lum * (1.0 + tint))) + else: + return int(round(lum * (1.0 - tint) + (HLSMAX - HLSMAX * (1.0 - tint)))) + + +def theme_and_tint_to_rgb(wb, theme, tint): + """Given a workbook, a theme number and a tint return a hex based rgb""" + rgb = get_theme_colors(wb)[theme] + h, l, s = rgb_to_ms_hls(rgb) + return rgb_to_hex(ms_hls_to_rgb(h, tint_luminance(tint, l), s)) + + +def get_color(wb, cell): + """get cell color; None for no fill""" + if not cell.fill.patternType: + return None + if isinstance(cell.fill.fgColor.rgb, str): + return "#" + cell.fill.fgColor.rgb[2:] + theme = cell.fill.start_color.theme + tint = cell.fill.start_color.tint + color = theme_and_tint_to_rgb(wb, theme, tint) + return "#" + color + + for tab in dataframe: print("parsing tab", tab.title) title = tab.title if title.lower() == "library_content": - print("...processing content") + print("processing library content") for row in tab: if any([r.value for r in row]): (v1, v2, v3) = (r.value for r in row[0:3]) @@ -140,7 +271,7 @@ def read_header(row): elif title not in library_vars_dict["tab"]: print(f"Ignored tab: {title}") elif library_vars_dict["tab"][title] == "requirements": - print("...processing requirements") + print("processing requirements") root_nodes_urn = re.sub("framework", "req_node", library_vars["framework_urn"]) current_node_urn = None current_depth = 0 @@ -217,7 +348,7 @@ def read_header(row): if annotation: req_node["annotation"] = annotation if implementation_groups: - req_node["implementation_groups"] = implementation_groups.split(',') + req_node["implementation_groups"] = implementation_groups.split(",") threats = row[header["threats"]].value if "threats" in header else None reference_controls = ( row[header["reference_controls"]].value @@ -253,7 +384,7 @@ def read_header(row): pass # print("empty row") elif library_vars_dict["tab"][title] == "reference_controls": - print("...processing reference controls") + print("processing reference controls") current_function = {} is_header = True reference_controls_base_urn = library_vars["reference_control_base_urn"] @@ -294,7 +425,7 @@ def read_header(row): current_function["annotation"] = annotation reference_controls.append(current_function) elif library_vars_dict["tab"][title] == "threats": - print("...processing threats") + print("processing threats") current_threat = {} is_header = True threat_base_urn = library_vars["threat_base_urn"] @@ -331,7 +462,7 @@ def read_header(row): current_threat["annotation"] = annotation threats.append(current_threat) elif library_vars_dict["tab"][title] == "scores": - print("...processing scores") + print("processing scores") is_header = True for row in tab: if is_header: @@ -348,7 +479,7 @@ def read_header(row): {"score": score, "name": name, "description": description} ) elif library_vars_dict["tab"][title] == "implementation_groups": - print("...processing implementation groups") + print("processing implementation groups") is_header = True for row in tab: if is_header: @@ -364,7 +495,63 @@ def read_header(row): implementation_groups_definition.append( {"ref_id": ref_id, "name": name, "description": description} ) - + elif library_vars_dict["tab"][title] == "risk_matrix": + print("processing risk matrix") + risk_matrix["urn"] = library_vars["risk_matrix_urn"] + risk_matrix["ref_id"] = library_vars["risk_matrix_ref_id"] + risk_matrix["name"] = library_vars["risk_matrix_name"] + risk_matrix["description"] = library_vars["risk_matrix_description"] + risk_matrix["probability"] = [] + risk_matrix["impact"] = [] + risk_matrix["risk"] = [] + risk_matrix["grid"] = [] + grid = {} + grid_color = {} + is_header = True + for row in tab: + if is_header: + header = read_header(row) + is_header = False + assert "type" in header + assert "id" in header + assert "color" in header + assert "abbreviation" in header + assert "name" in header + assert "description" in header + assert "grid" in header + elif any([c.value for c in row]): + ctype = row[header["type"]].value + assert ctype in ("probability", "impact", "risk") + id = row[header["id"]].value + color = get_color(dataframe, row[header["color"]]) + abbreviation = row[header["abbreviation"]].value + name = row[header["name"]].value + description = row[header["description"]].value + object = { + "id": id, + "abbreviation": abbreviation, + "name": name, + "description": description, + } + if color: + object["hexcolor"] = color + risk_matrix[ctype].append(object) + if ctype == "probability": + grid[id] = [c.value for c in row[6:]] + grid_color[id] = [get_color(dataframe, c) for c in row[6:]] + risk_matrix["grid"] = [grid[id] for id in sorted(grid)] + for id in grid: + for i, risk_id in enumerate(grid[id]): + risk_color = ( + risk_matrix["risk"][risk_id]["hexcolor"] + if "hexcolor" in risk_matrix["risk"][risk_id] + else None + ) + if not risk_color == grid_color[id][i]: + print(f"color mismatch for risk id {risk_id}") + exit(1) + for t in ("probability", "impact", "risk"): + risk_matrix[t].sort(key=lambda c: c["id"]) has_framework = "requirements" in [ library_vars_dict["tab"][x] for x in library_vars_dict["tab"] @@ -404,13 +591,19 @@ def read_header(row): "description": library_vars["framework_description"], } if "framework_min_score" in library_vars: - library["objects"]["framework"]["min_score"] = library_vars["framework_min_score"] + library["objects"]["framework"]["min_score"] = library_vars[ + "framework_min_score" + ] if "framework_max_score" in library_vars: - library["objects"]["framework"]["max_score"] = library_vars["framework_max_score"] + library["objects"]["framework"]["max_score"] = library_vars[ + "framework_max_score" + ] if scores_definition: library["objects"]["framework"]["scores_definition"] = scores_definition if implementation_groups_definition: - library["objects"]["framework"]["implementation_groups_definition"] = implementation_groups_definition + library["objects"]["framework"]["implementation_groups_definition"] = ( + implementation_groups_definition + ) library["objects"]["framework"]["requirement_nodes"] = requirement_nodes if has_reference_controls: @@ -419,6 +612,10 @@ def read_header(row): if has_threats: library["objects"]["threats"] = threats +if risk_matrix: + library["objects"]["risk_matrix"] = [risk_matrix] + + print("generating", output_file_name) with open(output_file_name, "w", encoding="utf8") as file: yaml.dump(library, file, sort_keys=False) diff --git a/tools/matrix/3x3-mult/risk-matrix-3x3-mult.xlsx b/tools/matrix/3x3-mult/risk-matrix-3x3-mult.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b5142c6c5cc3f10a4838da88cdf73e89c273aad3 GIT binary patch literal 11337 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 literal 0 HcmV?d00001 diff --git a/tools/matrix/5x5-sensitive/risk-matrix-5x5-sensitive.xlsx b/tools/matrix/5x5-sensitive/risk-matrix-5x5-sensitive.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2e63beb4b68d863503a9655b03dcf69f52553946 GIT binary patch literal 12496 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 Date: Tue, 7 May 2024 02:44:20 +0200 Subject: [PATCH 5/5] revert renaming folder to Domain, which breaks functional tests another solution is required --- frontend/messages/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index e73e612d5..383c0b422 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -94,7 +94,7 @@ "residualLevel": "Residual level", "riskMatrix": "Risk matrix", "project": "Project", - "folder": "Domain", + "folder": "Folder", "riskAssessment": "Risk assessment", "threat": "Threat", "framework": "Framework",