Skip to content

Commit

Permalink
Implement analysis of model from edit model view
Browse files Browse the repository at this point in the history
  • Loading branch information
Yevhen Zavhorodnii committed Nov 20, 2024
1 parent 99563ce commit b25efa3
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 2 deletions.
5 changes: 5 additions & 0 deletions pkg/model/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ func ReadAndAnalyzeModel(config configReader, builtinRiskRules types.RiskRules,
return nil, fmt.Errorf("unable to load model yaml: %w", loadError)
}

return AnalyzeModel(modelInput, config, builtinRiskRules, customRiskRules, progressReporter)
}

func AnalyzeModel(modelInput *input.Model, config configReader, builtinRiskRules types.RiskRules, customRiskRules types.RiskRules, progressReporter types.ProgressReporter) (*ReadResult, error) {

parsedModel, parseError := ParseModel(config, modelInput, builtinRiskRules, customRiskRules)
if parseError != nil {
return nil, fmt.Errorf("unable to parse model yaml: %w", parseError)
Expand Down
46 changes: 46 additions & 0 deletions pkg/server/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
"strings"

"github.com/gin-gonic/gin"
"github.com/threagile/threagile/pkg/input"
"github.com/threagile/threagile/pkg/model"
"github.com/threagile/threagile/pkg/risks"
)

func (s *server) analyze(ginContext *gin.Context) {
Expand Down Expand Up @@ -227,3 +230,46 @@ func (s *server) doItViaRuntimeCall(modelFile string, outputDir string,
}
}
}

func (s *server) editModelAnalyze(ginContext *gin.Context) {
defer func() {
var err error
if r := recover(); r != nil {
s.errorCount++
err = r.(error)
log.Println(err)
ginContext.JSON(http.StatusBadRequest, gin.H{
"error": strings.TrimSpace(err.Error()),
})
}
}()

var modelInput input.Model
if err := ginContext.ShouldBindJSON(&modelInput); err != nil {
ginContext.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid JSON provided",
})
return
}
log.Printf("Received JSON: %+v\n", modelInput)

progressReporter := DefaultProgressReporter{
Verbose: s.config.GetVerbose(),
SuppressError: true,
}
customRiskRules := model.LoadCustomRiskRules(s.config.GetPluginFolder(), s.config.GetRiskRulePlugins(), progressReporter)
builtinRiskRules := risks.GetBuiltInRiskRules()

result, err := model.AnalyzeModel(&modelInput, s.config, builtinRiskRules, customRiskRules, progressReporter)
if err != nil {
ginContext.JSON(http.StatusBadRequest, gin.H{
"error": "Unable to analyze model: " + err.Error(),
})
return
}

ginContext.JSON(http.StatusOK, gin.H{
"message": "JSON received successfully",
"data": result,
})
}
50 changes: 50 additions & 0 deletions pkg/server/progress-reporter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package server

import (
"fmt"
"log"
)

type DefaultProgressReporter struct {
Verbose bool
SuppressError bool
}

func (r DefaultProgressReporter) Info(a ...any) {
if r.Verbose {
fmt.Println(a...)
}
}

func (DefaultProgressReporter) Warn(a ...any) {
fmt.Println(a...)
}

func (r DefaultProgressReporter) Error(v ...any) {
if r.SuppressError {
r.Warn(v...)
return
}
log.Fatal(v...)
}

func (r DefaultProgressReporter) Infof(format string, a ...any) {
if r.Verbose {
fmt.Printf(format, a...)
fmt.Println()
}
}

func (DefaultProgressReporter) Warnf(format string, a ...any) {
fmt.Print("WARNING: ")
fmt.Printf(format, a...)
fmt.Println()
}

func (r DefaultProgressReporter) Errorf(format string, v ...any) {
if r.SuppressError {
r.Warnf(format, v...)
return
}
log.Fatalf(format, v...)
}
5 changes: 5 additions & 0 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ type serverConfigReader interface {
GetDataAssetDiagramFilenameDOT() string
GetReportFilename() string
GetExcelRisksFilename() string
GetRiskExcelConfigHideColumns() []string
GetRiskExcelConfigSortByColumns() []string
GetRiskExcelConfigWidthOfColumns() map[string]float64
GetExcelTagsFilename() string
GetJsonRisksFilename() string
GetJsonTechnicalAssetsFilename() string
Expand Down Expand Up @@ -170,6 +173,8 @@ func RunServer(config serverConfigReader, builtinRiskRules types.RiskRules) {

router.GET("/meta/stats", s.stats)

router.POST("/edit-model/analyze", s.editModelAnalyze)

router.POST("/direct/analyze", s.analyze)
router.POST("/direct/check", s.check)
router.GET("/direct/stub", s.stubFile)
Expand Down
3 changes: 2 additions & 1 deletion server/static/edit-model.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<div class="buttons-container">
<button id="btnRestoreChanges">Restore Changes</button>
<button id="btnExportDiagram">Export</button>
<button id="btnAnalyze">Analyze</button>
</div>

<div class="diagram-container">
Expand All @@ -42,7 +43,7 @@
</div>
<div class="diagram-container">
<div id="riskTrackingPropertyEditor" class="risk-property-editor"></div>
<div id="riskPropertyEditor" class="risk-property-editor"></div>
<div id="riskAnalyzeContent" class="risk-property-editor">
</div>
</body>
<script src="./js/schema.js"></script>
Expand Down
77 changes: 77 additions & 0 deletions server/static/js/edit-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,31 @@ $(document).ready(function() {
}
});

$('#btnAnalyze').on('click', function() {
try {
$.ajax({
url: "/edit-model/analyze",
type: "POST",
contentType: "application/json",
data: JSON.stringify(diagramYaml),
success: function(response) {
const risksByCategory = response.data.ParsedModel.generated_risks_by_category;
renderRiskTables(risksByCategory);
},
error: function(jqXHR, textStatus, errorThrown) {
$("#riskAnalyzeContent").html("Error happened: <span>" + jqXHR.responseJSON.error + "</span>")
console.error("Request failed:", textStatus, errorThrown);
alert('Analysis failed');
}
});

} catch (e) {

console.error("Error analyzing model")
}

});

function nodeClicked(e, obj) {
var evt = e.copy();
var node = obj.part;
Expand Down Expand Up @@ -219,4 +244,56 @@ $(document).ready(function() {
"data_assets_received": data_assets
}
}

function renderRiskTables(generatedRisksByCategory) {
const container = $("#riskAnalyzeContent");
container.empty(); // Clear any existing content

// Iterate over each category in the risks object
$.each(generatedRisksByCategory, function(category, risks) {
// Create a table for the category
const table = $("<table>").addClass("risk-table").css({
border: "1px solid black",
width: "100%",
marginBottom: "20px"
});

// Add a caption for the category
const caption = $("<caption>")
.text(`Category: ${category}`)
.css({ fontWeight: "bold", textAlign: "left", marginBottom: "10px" });
table.append(caption);

// Add a header row
const headerRow = $("<tr>").append(
$("<th>").text("Synthetic ID"),
$("<th>").text("Title"),
$("<th>").text("Severity"),
$("<th>").text("Likelihood"),
$("<th>").text("Impact"),
$("<th>").text("Most Relevant Asset"),
$("<th>").text("Communication Link"),
$("<th>").text("Data Breach Assets")
).css({ backgroundColor: "#f2f2f2", textAlign: "left" });
table.append(headerRow);

// Add a row for each risk
risks.forEach(risk => {
const row = $("<tr>").append(
$("<td>").text(risk.synthetic_id),
$("<td>").html(risk.title),
$("<td>").text(risk.severity),
$("<td>").text(risk.exploitation_likelihood),
$("<td>").text(risk.exploitation_impact),
$("<td>").text(risk.most_relevant_technical_asset || "N/A"),
$("<td>").text(risk.most_relevant_communication_link || "N/A"),
$("<td>").text(risk.data_breach_technical_assets.join(", ") || "N/A")
).css({ borderBottom: "1px solid black" });
table.append(row);
});

// Append the table to the container
container.append(table);
});
}
});
4 changes: 3 additions & 1 deletion server/static/js/property-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class EditorGenerator {
this.object[key] = input.val();
callback(key, input.val());
});
input.datepicker();
input.datepicker({
dateFormat: "yy-mm-dd" // ISO 8601 format
});
} else if (property.enum) {
input = $('<select>')
.addClass('property-editor-input')
Expand Down

0 comments on commit b25efa3

Please sign in to comment.