BE - GraphQL Support for Total Risk Score
Problem to Solve
In this issue we focus on the backend work for the Security Dashboard, Total Risk Score &17425
In Scope
Panel Level
- Grouping by Project
Page Level
- Filtering by Project
- Filtering by Report Type
Out of Scope
Page Level
- Severity filter
- Report Type filter
- Scanner filter
- Time/date range (is “time” meant as date range?)
- Grouping by anything other than project
Panel Level
- Grouping by
- Severity filtering
- Scanner filter
- Date range
Other
- Business context
- Environment
- Secret status/validity
- Business Impact
- Exposure
Dependencies
- Dependency of: groupsecurity infrastructure
Implementation Plan
Phase 1
- Add feature flag (e.g.
new_security_dashboard_total_risk_score) - Add GraphQL Schema Extensions
-
Create
RiskScoreTypewith fields:scoreratingfactorsby_project
-
Create
RiskFactorsType(make all fields nullable for now)vulnerabilities_average_score
Once &17425 (comment 2683380788) has been confirmed, we can add:
update_frequencyenvironmentcode_visibility
-
Create
Security::RiskScoreResolver -
Create
RiskRatingenum-
low(0–25) -
medium(26–50) -
high(51–75) -
critical(76–100) unknown
-
-
Add
risk_scorefieldnull: true)to ofSecurityMetricsType -
Add testing
-
Implement Dummy Data - to unblock and test while developing (Phase 1) - See GraphQL Example Response for
-
Phase 2
- Integrate real backend when Epic #18188 completes and remove dummy data implementation (Phase 2)
Outstanding Questions
| Question | Answer | Assignee | Priority | Blocking? |
|---|---|---|---|---|
|
Will factor fields |
||||
|
Is |
Resources
GraphQL Example Query 1
Current Scope (until &17425 (comment 2683380788) has been confirmed)
query getGroupTotalRiskScore(
$fullPath: ID!
$projectId: [ProjectType!]
$reportType: [VulnerabilityReportType!]
$includeByProject: Boolean!
) {
group(fullPath: $fullPath) {
id
securityMetrics(projectId: $projectId) {
riskScore {
score
rating
factors {
vulnerabilitiesAverageScore {
factor
}
}
... @include(if: $includeByProject) {
byProject {
count
nodes {
project { # `Project` type
id
name
}
score
rating
}
}
}
}
}
}
}
GraphQL Example Response
{
"data": {
"group": {
"id": "gid://gitlab/Group/123",
"securityMetrics": {
"riskScore": {
"score": 5.2,
"rating": "MEDIUM",
"factors": {
"vulnerabilitiesAverageScore": {
"factor": 1.0
}
},
"byProject": {
"count": 2,
"nodes": [
{
"project": {
"id": "gid://gitlab/Project/123",
"name": "test-project"
},
"score": 5.2,
"rating": "MEDIUM"
}
]
}
}
}
}
}
}
GraphQL Example Query 2
Once &17425 (comment 2683380788) has been confirmed
query getGroupTotalRiskScore( # not sure about this naming
$fullPath: ID!
$projectId: [ProjectType!]
$reportType: [VulnerabilityReportType!]
$includeByProject: Boolean!
) {
group(fullPath: $fullPath) {
id
securityMetrics(projectId: $projectId, reportType: $reportType) {
riskScore {
score
rating
factors {
codeVisibility {
visibility
factor
}
environment {
name
factor
}
updateFrequency {
frequency
factor
}
vulnerabilitiesAverageScore {
factor
}
}
... @include(if: $includeByProject) {
byProject {
count
nodes {
project { # `Project` type
id
name
}
score
rating
}
}
}
}
}
}
}
{
"data": {
"group": {
"id": "gid://gitlab/Group/123",
"securityMetrics": {
"riskScore": {
"score": 5.2,
"rating": "MEDIUM",
"factors": {
"codeVisibility": {
"visibility": "Public",
"factor": 1.0
},
"environment": {
"name": "Production",
"factor": 1.0
},
"updateFrequency": {
"frequency": "Daily",
"factor": 1.0
},
"vulnerabilitiesAverageScore": {
"factor": 1.0
}
},
"byProject": {
"count": 2,
"nodes": [
{
"project": {
"id": "gid://gitlab/Project/123",
"name": "test-project"
},
"score": 5.2,
"rating": "MEDIUM"
}
]
}
}
}
}
}
}