Skip to content

Expose `has_ai_resolution` filter via GraphQL

What does this MR do and why?

Context

We need to be able to filter vulnerabilities on whether they have the "Resolve with Duo" button enabled.

This button is enabled if a finding's CWE value is included in this hard-coded list of CWE values.

In previous MRs we:

  • Added a new column to support this filter 1
  • Began populating this column for new rows 2
  • Added a batched background migration to backfill the new column 3

This MR

The database work isn't done yet as the backfill is still running and the indexes are not built yet 4.

However, we can expose graphql fields with FFs according to the docs:

This will unblock the frontend team from building and testing their code, as well as help us solidify the API contract.

SQL

Group level query

SELECT
    "vulnerability_reads"."id",
    "vulnerability_reads"."vulnerability_id",
    "vulnerability_reads"."project_id",
    "vulnerability_reads"."scanner_id",
    "vulnerability_reads"."report_type",
    "vulnerability_reads"."severity",
    "vulnerability_reads"."state",
    "vulnerability_reads"."has_issues",
    "vulnerability_reads"."resolved_on_default_branch",
    "vulnerability_reads"."uuid",
    "vulnerability_reads"."location_image",
    "vulnerability_reads"."cluster_agent_id",
    "vulnerability_reads"."casted_cluster_agent_id",
    "vulnerability_reads"."dismissal_reason",
    "vulnerability_reads"."has_merge_request",
    "vulnerability_reads"."has_remediations",
    "vulnerability_reads"."owasp_top_10",
    "vulnerability_reads"."traversal_ids",
    "vulnerability_reads"."archived",
    "vulnerability_reads"."identifier_names",
    "vulnerability_reads"."has_vulnerability_resolution"
FROM
    "vulnerability_reads"
WHERE
    "vulnerability_reads"."traversal_ids" >= '{9970}'
    AND "vulnerability_reads"."traversal_ids" < '{9971}'
    AND "vulnerability_reads"."archived" = FALSE
    AND "vulnerability_reads"."report_type" IN (6, 2, 5, 3, 1, 0, 4, 99)
    AND "vulnerability_reads"."severity" IN (1, 2, 4, 5, 6, 7)
    AND "vulnerability_reads"."state" IN (1, 4)
    AND "vulnerability_reads"."resolved_on_default_branch" = FALSE
    AND "vulnerability_reads"."has_vulnerability_resolution" = TRUE
ORDER BY
    "vulnerability_reads"."severity" DESC,
    "vulnerability_reads"."traversal_ids" DESC,
    "vulnerability_reads"."vulnerability_id" DESC
LIMIT 21

Project level query

SELECT
    "vulnerability_reads"."id",
    "vulnerability_reads"."vulnerability_id",
    "vulnerability_reads"."project_id",
    "vulnerability_reads"."scanner_id",
    "vulnerability_reads"."report_type",
    "vulnerability_reads"."severity",
    "vulnerability_reads"."state",
    "vulnerability_reads"."has_issues",
    "vulnerability_reads"."resolved_on_default_branch",
    "vulnerability_reads"."uuid",
    "vulnerability_reads"."location_image",
    "vulnerability_reads"."cluster_agent_id",
    "vulnerability_reads"."casted_cluster_agent_id",
    "vulnerability_reads"."dismissal_reason",
    "vulnerability_reads"."has_merge_request",
    "vulnerability_reads"."has_remediations",
    "vulnerability_reads"."owasp_top_10",
    "vulnerability_reads"."traversal_ids",
    "vulnerability_reads"."archived",
    "vulnerability_reads"."identifier_names",
    "vulnerability_reads"."has_vulnerability_resolution"
FROM
    "vulnerability_reads"
WHERE
    "vulnerability_reads"."project_id" = 278964
    AND "vulnerability_reads"."report_type" IN (6, 2, 5, 3, 1, 0, 4, 99)
    AND "vulnerability_reads"."state" IN (1, 4)
    AND "vulnerability_reads"."resolved_on_default_branch" = FALSE
    AND "vulnerability_reads"."has_vulnerability_resolution" = TRUE
ORDER BY
    "vulnerability_reads"."severity" DESC,
    "vulnerability_reads"."vulnerability_id" DESC
LIMIT 21

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

How to set up and validate locally

You can query graphql locally using http://gdk.test:3000//-/graphql-explorer

example query
query groupVulnerabilities($fullPath: ID!, $before: String, $after: String, $first: Int = 20, $last: Int, $projectId: [ID!], $severity: [VulnerabilitySeverity!], $reportType: [VulnerabilityReportType!], $scanner: [String!], $scannerId: [VulnerabilitiesScannerID!], $state: [VulnerabilityState!], $dismissalReason: [VulnerabilityDismissalReason!], $sort: VulnerabilitySort, $hasIssues: Boolean, $hasResolution: Boolean, $hasMergeRequest: Boolean, $hasRemediations: Boolean, $vetEnabled: Boolean = false, $clusterAgentId: [ClustersAgentID!], $owaspTopTen: [VulnerabilityOwaspTop10!]) {
  group(fullPath: $fullPath) {
    id
    vulnerabilities(
      before: $before
      after: $after
      first: $first
      last: $last
      severity: $severity
      reportType: $reportType
      scanner: $scanner
      scannerId: $scannerId
      state: $state
      dismissalReason: $dismissalReason
      projectId: $projectId
      sort: $sort
      hasIssues: $hasIssues
      hasAiResolution: false
      hasResolution: $hasResolution
      hasMergeRequest: $hasMergeRequest
      hasRemediations: $hasRemediations
      clusterAgentId: $clusterAgentId
      owaspTopTen: $owaspTopTen
    ) {
      nodes {
        ...VulnerabilityFragment
        __typename
      }
      pageInfo {
        ...PageInfo
        __typename
      }
      __typename
    }
    __typename
  }
}

fragment VulnerabilityFragment on Vulnerability {
  id
  title
  state
  severity
  detectedAt
  dismissalReason
  vulnerabilityPath
  resolvedOnDefaultBranch
  userNotesCount
  falsePositive @include(if: $vetEnabled)
  hasRemediations
  mergeRequest {
    id
    webUrl
    state
    iid
    __typename
  }
  identifiers {
    externalType
    name
  }
  project {
    id
    nameWithNamespace
    __typename
  }
  reportType
  scanner {
    id
    vendor
    __typename
  }
  __typename
}


fragment PageInfo on PageInfo {
  hasNextPage
  hasPreviousPage
  startCursor
  endCursor
  __typename
}

variables:

{
		"dismissalReason": [],
		"first": 20,
		"fullPath": "gitlab-org",
		"hasResolution": false,
		"last": null,
		"reportType": [
			"API_FUZZING",
			"CONTAINER_SCANNING",
			"COVERAGE_FUZZING",
			"DAST",
			"DEPENDENCY_SCANNING",
			"SAST",
			"SECRET_DETECTION",
			"GENERIC"
		],
		"sort": "severity_desc",
		"state": [
			"DETECTED",
			"CONFIRMED"
		],
		"vetEnabled": true
	}

Changelog: Added
EE: true
Resolves: #490323 (closed)
Epic: &15036 (closed)

  1. Add `has_vulnerability_resolution` column to `v... (!165548 - merged) • Michael Becker • 17.5

  2. Begin populating the `has_vulnerability_resolut... (!165952 - merged) • Michael Becker • 17.5

  3. Backfill for `vulnerability_reads.has_vulnerabi... (!166110 - merged) • Michael Becker • 17.5

  4. The index addition was being pushed off due to the difficulty of testing an index in database lab until the backfill is complete. This thread has more discussion. We ended up adding an index migration to this MR after the discussion in this thread

Edited by Michael Becker

Merge request reports

Loading