Skip to content

Commit

Permalink
fix: add GetJobReportSummaryResponse api
Browse files Browse the repository at this point in the history
  • Loading branch information
artaasadi committed Dec 17, 2024
1 parent bf92c36 commit c1fa50a
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 3 deletions.
40 changes: 40 additions & 0 deletions services/compliance/api/audit_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"github.com/opengovern/opencomply/pkg/types"
"time"
)

type AuditSummary struct {
Expand All @@ -10,3 +11,42 @@ type AuditSummary struct {
AuditSummary map[types.ComplianceStatus]uint64 `json:"audit_summary"`
JobSummary types.JobSummary `json:"job_summary"`
}

type GetJobReportSummaryJobDetails struct {
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Framework struct {
ID string `json:"id"`
Title string `json:"title"`
} `json:"framework"`
IntegrationIDs []string `json:"integration_ids"`
JobScore JobScore `json:"job_score"`
Results GetJobReportSummaryJobDetailsResults `json:"results"`
}

type GetJobReportSummaryJobDetailsResults struct {
Alarm uint64 `json:"alarm"`
Ok uint64 `json:"ok"`
}

type JobScore struct {
TotalControls int64 `json:"total_controls"`
FailedControls int64 `json:"failed_controls"`
ControlView JobScoreControlView `json:"control_view"`
}

type JobScoreControlView struct {
BySeverity map[string]*JobScoreControlViewBySeverityScore `json:"by_severity"`
}

type JobScoreControlViewBySeverityScore struct {
TotalControls uint64 `json:"total_controls"`
FailedControls uint64 `json:"failed_controls"`
}

type GetJobReportSummaryResponse struct {
JobID uint `json:"job_id"`
WithIncidents bool `json:"with_incidents"`
JobDetails GetJobReportSummaryJobDetails `json:"job_details"`
}
118 changes: 115 additions & 3 deletions services/compliance/http_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ func (h *HttpHandler) Register(e *echo.Echo) {
v3.GET("/quick/scan/:run_id", httpserver2.AuthorizeHandler(h.GetQuickScanSummary, authApi.ViewerRole))
v3.GET("/quick/sequence/:run_id", httpserver2.AuthorizeHandler(h.GetQuickSequenceSummary, authApi.ViewerRole))

v3.GET("/compliance/report/:run_id", httpserver2.AuthorizeHandler(h.GetComplianceJobReport, authApi.ViewerRole))
v3.GET("/job-report/:run_id/summary", httpserver2.AuthorizeHandler(h.GetComplianceJobReport, authApi.ViewerRole))
v3.GET("/job-report/:run_id/details/by-control", httpserver2.AuthorizeHandler(h.GetComplianceJobReport, authApi.ViewerRole))
v3.GET("/job-report/:run_id/summary", httpserver2.AuthorizeHandler(h.GetJobReportSummary, authApi.ViewerRole))
}

func bindValidate(ctx echo.Context, i any) error {
Expand Down Expand Up @@ -7856,7 +7856,7 @@ func (h HttpHandler) GetQuickSequenceSummary(c echo.Context) error {
// @Param with_incidents query bool false "Whether the job was with incidents or not"
// @Param run_id path string true "compliance summary job id"
// @Success 200
// @Router /compliance/api/v3/compliance/report/{run_id} [get]
// @Router /compliance/api/v3/job-report/:run_id/details/by-control [get]
func (h HttpHandler) GetComplianceJobReport(c echo.Context) error {
clientCtx := &httpclient.Context{UserRole: authApi.AdminRole}

Expand Down Expand Up @@ -7893,3 +7893,115 @@ func (h HttpHandler) GetComplianceJobReport(c echo.Context) error {

return c.JSON(http.StatusOK, summary)
}

// GetJobReportSummary godoc
//
// @Summary Get Job Report Summary
// @Description Get Job Report Summary
// @Security BearerToken
// @Tags workspace
// @Accept json
// @Produce json
// @Param controls query []string false "List of controls to get results"
// @Param with_incidents query bool false "Whether the job was with incidents or not"
// @Param run_id path string true "compliance summary job id"
// @Success 200
// @Router /compliance/api/v3/job-report/:run_id/summary [get]
func (h HttpHandler) GetJobReportSummary(ctx echo.Context) error {
clientCtx := &httpclient.Context{UserRole: authApi.AdminRole}

jobId := ctx.Param("run_id")
controlsFilter := httpserver2.QueryArrayParam(ctx, "controls")

complianceJob, err := h.schedulerClient.GetComplianceJobStatus(clientCtx, jobId)
if err != nil {
h.logger.Error("failed to get compliance job", zap.Error(err))
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get compliance job")
}
if complianceJob.JobStatus == string(schedulerapi.ComplianceJobFailed) {
return echo.NewHTTPError(http.StatusBadRequest, "job has been failed")
} else if complianceJob.JobStatus == string(schedulerapi.ComplianceJobTimeout) {
return echo.NewHTTPError(http.StatusBadRequest, "job has been timed out")
} else if complianceJob.JobStatus == string(schedulerapi.ComplianceJobRunnersInProgress) ||
complianceJob.JobStatus == string(schedulerapi.ComplianceJobCreated) ||
complianceJob.JobStatus == string(schedulerapi.ComplianceJobSummarizerInProgress) {
return echo.NewHTTPError(http.StatusBadRequest, "job is in progress")
}
if complianceJob.WithIncidents {
if complianceJob.SummaryJobId == nil {
return echo.NewHTTPError(http.StatusBadRequest, "compliance job not summarized yet")
}
jobId = strconv.Itoa(int(*complianceJob.SummaryJobId))
}

framework, err := h.db.GetBenchmark(ctx.Request().Context(), complianceJob.BenchmarkId)
if err != nil {
h.logger.Error("failed to get framework by frameworkID", zap.String("framework", complianceJob.BenchmarkId), zap.Error(err))
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get framework by frameworkID")
}

controlsMap, err := h.getControlsUnderBenchmark(ctx.Request().Context(), complianceJob.BenchmarkId, make(map[string]BenchmarkControlsCache))
if err != nil {
h.logger.Error("failed to get controls under benchmark", zap.String("framework", complianceJob.BenchmarkId), zap.Error(err))
return echo.NewHTTPError(http.StatusInternalServerError, "could not get framework by frameworkID")
}
var controlsStr []string
for c, _ := range controlsMap {
controlsStr = append(controlsStr, c)
}
controls, err := h.db.ListControls(ctx.Request().Context(), controlsStr, nil)

summary, err := es.GetJobReportControlSummaryByJobID(ctx.Request().Context(), h.logger, h.client,
jobId, complianceJob.WithIncidents, controlsFilter)
if err != nil {
h.logger.Error("failed to get job report control summary by job id", zap.Error(err))
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get job report control summary by job id")
}

response := api.GetJobReportSummaryResponse{
JobID: complianceJob.JobId,
WithIncidents: complianceJob.WithIncidents,
JobDetails: api.GetJobReportSummaryJobDetails{
Status: complianceJob.JobStatus,
CreatedAt: complianceJob.CreatedAt,
UpdatedAt: complianceJob.UpdatedAt,
Framework: struct {
ID string `json:"id"`
Title string `json:"title"`
}{
ID: framework.ID,
Title: framework.Title,
},
IntegrationIDs: []string{complianceJob.IntegrationInfo.IntegrationID},
Results: api.GetJobReportSummaryJobDetailsResults{
Ok: summary.ComplianceSummary[types2.ComplianceStatusOK],
Alarm: summary.ComplianceSummary[types2.ComplianceStatusALARM],
},
},
}
jobScore := api.JobScore{
TotalControls: summary.ControlScore.TotalControls,
FailedControls: summary.ControlScore.FailedControls,
ControlView: api.JobScoreControlView{
BySeverity: make(map[string]*api.JobScoreControlViewBySeverityScore),
},
}
for _, c := range controls {
if _, ok := jobScore.ControlView.BySeverity[c.Severity.String()]; !ok {
jobScore.ControlView.BySeverity[c.Severity.String()] = &api.JobScoreControlViewBySeverityScore{}
}
jobScore.ControlView.BySeverity[c.Severity.String()].TotalControls += 1
}

for _, cs := range summary.Controls {
if _, ok := jobScore.ControlView.BySeverity[cs.Severity.String()]; !ok {
jobScore.ControlView.BySeverity[cs.Severity.String()] = &api.JobScoreControlViewBySeverityScore{}
}
if cs.Alarms > 0 {
jobScore.ControlView.BySeverity[cs.Severity.String()].FailedControls += 1
}
}
response.JobDetails.JobScore = jobScore

return ctx.JSON(http.StatusOK, response)
}

0 comments on commit c1fa50a

Please sign in to comment.