Expose triage and remediation profile configuration input types

What does this MR do and why?

Adds the GraphQL input types for create and update a triage_and_remediation scan profile with a configuration per trigger.

SecurityScanProfileConfigurationInput is a one_of keyed by scan type, but triage_and_remediation selects its JSON schema by trigger type, so its new member is itself a one_of: SecurityScanProfileTriageAndRemediationConfigurationInput, with one argument per trigger type. Mutations::Security::ScanProfiles::TriggerArguments unwraps both levels and rejects a configuration whose member does not name the trigger it is attached to.

Argument Input type Arguments
sastFalsePositive SecurityScanProfileSastFalsePositiveInput severityLevel, cweClasses, runMode
sastVulnerabilityResolution SecurityScanProfileSastVulnerabilityResolutionInput severityLevel, cweClasses, runMode, openMergeRequestsLimit, falsePositiveConfidence
secretDetectionFalsePositive SecurityScanProfileSecretDetectionFalsePositiveInput runMode
vulnerabilityEnrichment SecurityScanProfileVulnerabilityEnrichmentInput severityLevel, runMode
sbomIngested existing SecurityScanProfileDependencyScanningPostProcessingConfigurationInput reused as-is

Validations:

  • SecurityScanProfileRunMode and SecurityScanProfileFalsePositiveConfidence are enums
  • New input-only CweIdentifier scalar enforcing ^CWE-\d{1,5}$, and a 50-item cap on cweClasses.

Mutations::Security::ScanProfiles::Update also gained the triage_and_remediation_profile check that Create already had - without it, a profile created while the flag was on stayed editable after the flag was turned off.

All new arguments and enum values are tagged experiment: { milestone: '19.4' }.

Changelog: added
EE: true

[Backend] Add input types for new configurations (#627239 - closed) • Gal Katz

How to set up and validate locally

  1. Enable the flags in the Rails console:

    Feature.enable(:triage_and_remediation_profile)
  2. Create a profile with a configuration per trigger for root group g:

    mutation {
      securityScanProfileCreate(
        input: {
          namespaceId: "gid://gitlab/Group/<g.id>"
          scanType: TRIAGE_AND_REMEDIATION
          name: "Triage via GraphQL"
          description: "Created through the mutation"
          triggers: [
            {
              triggerType: SAST_VULNERABILITY_RESOLUTION
              configuration: {
                triageAndRemediation: {
                  sastVulnerabilityResolution: {
                    severityLevel: CRITICAL
                    runMode: MANUAL
                    cweClasses: ["CWE-89"]
                    openMergeRequestsLimit: 3
                    falsePositiveConfidence: LIKELY_NOT_FALSE_POSITIVE
                  }
                }
              }
            }
            {
              triggerType: VULNERABILITY_ENRICHMENT
              configuration: {
                triageAndRemediation: {
                  vulnerabilityEnrichment: { severityLevel: INFO }
                }
              }
            }
            {
              triggerType: SBOM_INGESTED
              configuration: {
                triageAndRemediation: {
                  sbomIngested: {
                    autoRemediation: { cooldown: 3, upgradePolicy: MAJOR }
                  }
                }
              }
            }
          ]
        }
      ) {
        errors
        scanProfile {
          id
          name
          triggers
        }
      }
    }
  3. Confirm errors is empty and each trigger member landed on its own trigger, with values equal to the Standard defaults stripped out:

    profile = Security::ScanProfile.find_by(name: 'Triage via GraphQL')
    profile.scan_profile_triggers.each do |trigger|
      puts "#{trigger.trigger_type}: #{trigger.configuration&.configuration.inspect}"
    end
    sast_vulnerability_resolution: {"severity_level"=>"critical", "run_mode"=>"manual", "cwe_classes"=>["CWE-89"], "open_merge_requests_limit"=>3, "false_positive_confidence"=>"likely_not_false_positive"}
    vulnerability_enrichment: {"severity_level"=>"info"}
    sbom_ingested: {"auto_remediation"=>{"cooldown"=>3, "upgrade_policy"=>"major"}}
  4. Update the profile: Replacing a trigger's configuration overwrites it; sending a trigger with no configuration removes its stored configuration; omitting a trigger removes the trigger:

    mutation {
      securityScanProfileUpdate(
        input: {
          id: "gid://gitlab/Security::ScanProfile/<ID>"
          triggers: [
            {
              triggerType: SAST_VULNERABILITY_RESOLUTION
              configuration: {
                triageAndRemediation: {
                  sastVulnerabilityResolution: {
                    severityLevel: LOW
                    falsePositiveConfidence: LIKELY_FALSE_POSITIVE
                  }
                }
              }
            }
            { triggerType: VULNERABILITY_ENRICHMENT }
          ]
        }
      ) {
        errors
        scanProfile {
          triggers
        }
      }
    }

    Re-run the console snippet from the previous step. sast_vulnerability_resolution is now {"severity_level"=>"low", "false_positive_confidence"=>"likely_false_positive"}, vulnerability_enrichment is nil, and sbom_ingested is gone.

  5. Confirm the rejections, each by changing the create mutation:

    Change Expected error
    Pair triggerType: SBOM_INGESTED with a sastFalsePositive member Configuration 'sast_false_positive' does not match trigger type 'sbom_ingested'
    Use a secretDetection member instead of triageAndRemediation Configuration 'secret_detection' does not match scan type 'triage_and_remediation'
    cweClasses: ["sql-injection"] "sql-injection" is not a valid CWE identifier
    51 entries in cweClasses cweClasses is too long (maximum is 50)
  6. With Feature.disable(:triage_and_remediation_profile), re-running the update mutation returns a top-level resource-not-available error instead of applying the change.

MR acceptance checklist

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

Merge request reports

Loading
Loading