Security Analyzer Configuration Profiles

This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
proposed theoretick ahmed.hemdan or-gal g.hickman sec security risk management 2024-10-31

Summary

We need a scalable way of storing and injecting analyzer configuration between security analyzers and Gitlab Rails. By introducing persisted configuration profiles we can provide an explicit and injectable list of configuration options to be used when executing a security scan.

Motivation

Configuration is a comprehensive categorical definition of all user-modifiable behavior around execution of GitLab’s security scans. This includes log levels, file path exclusions, number of cores utilized, and the rules under test.

Analyzer configuration was first designed for CI-based scans, but increasingly, GitLab security analyzers are moving outside of pipelines. For CI-based analyzers, we have traditionally relied on exposing CI variables in the corresponding components and templates which are passed to each analyzer for configuring the execution of a scan.

There are several challenges with this approach:

  • Difficulty in configuring scans performed outside of CI contexts (e.g. Secret Push Protection and Continuous Vulnerability Scanning)
  • Inconsistent configuration profiles between different scan contexts
  • Inability to store user-defined configurations uniformally
  • Inability to scale shared configuration to organization-wide levels

There’s also a growing need to standardize configuration and store user-defined configurations in a consistent and scalable manner.

Goals

Provide GitLab users with a way to:

  • Securely store default analyzer configurations within GitLab
  • Securely store user-defined analyzer configurations within GitLab
  • Manage multiple configuration profiles
  • Inject configuration profiles into all possible scan contexts
  • Validate all possible configuration values for each supported analyzer
  • Manage configuration profiles at a group and project level
    • Excludes organization profiles
  • Get visibility into what has been configured, and to which projects that configuration has been applied

Use cases

Sequence for CI-based scan

sequenceDiagram
    autonumber
    Analyzer->>+Rails: Provide list of configuration options via versioned configuration schema
    Rails-->>+Analyzer: Use user-defined overrides + defaults
    Analyzer->>Analyzer: Execute scan with configuration profile
    Analyzer->>-Analyzer: Generate report with configuration used
    Analyzer->>+Rails: Store security report
    Rails-->>-Rails: Store scan configuration

Non-Goals

Configuration Profiles are focused entirely on the way in which an analyzer executes its scan. The context by which a scan is ran (i.e. within CI, upon registry push, upon git push, etc..) is out of scope from the initial design.

Terminology

  • Scan - Execution of software that scans for vulnerabilities (see Analyzer and Scanner glossary)

  • Rule modification - changes to a single predefined rule used by a analyzer; i.e. severity overrides or rule pattern augmentation

  • Ruleset - the collection of rules a single analyzer uses; for example “GitLab Advanced SAST’s ruleset is composed of 100 rules”

  • Rule - A collection of patterns associated with an identifiable vulnerability. A rule has a unique identifier and metadata (i.e. severity).

  • Rule augmentation - A rule whose pattern has been modified to increase specificity or scope of detection

  • Rule exclusion - A rule that has been disabled for a given scan profile configuration

  • Rule override - A rule whose metadata properties have been overridden; i.e. a change in severity

  • Enablement - When an analyzer has been configured to run by default for a given project and detection context

  • Enforcement - When an analyzer has been “enabled” and can only be disabled by elevated permissions

  • Execution - When a scan has been triggered for a given analyzer

Terms to Avoid

The following terms are broad, multifacted, and can lead to confusion in overlapping intent. They should be avoided without qualifiers.

  • Configuration
  • Customization

For example:

  • Prefer: “In Q1, we will support Scan Configuration Profiles. In Q2, we will support Scan Configuration Enforcement”
    • Not: “In Q1, we will support Scan Configuration”
  • Prefer: “In Q1, we will support Rule Exclusions. In Q2, we will support Rule Overrides”
    • Not: “In Q1, we will support Rule Customization”

Proposal

  1. Persistent Configuration Profiles
    1. Define data model for persisting group-level configuration profiles
    2. Support exclusions
      1. Associate path and value-based exclusions with configuration profiles
      2. Associate rule customization with configuration profiles
  2. Scan ruleset management
    1. Define syncing mechanism for persisting scan rules to GitLab Rails
  3. Scan configuration settings
    1. Define JSON schema encompassing all supported scan configuration options
    2. Develop API for persisting and managing user preferences as configuration profiles (validated against schema)
    3. Develop UI for persisting and managing user preferences as configuration profiles (validated against schema)
    4. Inject chosen** configuration profile into scan contexts (starting with CI)
    5. Update analyzers to prefer injected configuration settings, prioritizing over ENV and defaults
    6. Update analyzers to provide configuration used to execute each scan
    7. Generate audit events on configuration profile changes
    8. Create both a new default and new custom role for scan configuration profile modification

Configuration JSON schema

Example schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "",
  "title": "Security Scan Configuration Options",
  "description": "Mapping of all possible configuration options for Gitlab security scans",
  "type": "object",
  "properties": {
    "additional_ca_cert_bundle": {
        "description": "Bundle of CA certs that you want to trust.",
        "type": "string"
    },
    "log_level": {
        "description": "Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: fatal, error, warn, info, debug",
        "type": "string",
        "enum": ["fatal, error, warn, info, debug"],
        "default": "info"
    },
    "secret_detection_historic_scan": {
        "description": "Flag to enable a historic Gitleaks scan",
        "type": "boolean",
        "default": false
    },
  }
}

Configuration DB Schema

classDiagram
    class namespaces {
        id: bigint
        path: text
        ...
    }

    class projects {
        id: bigint
        path: text
        ...
    }

    class security_scan_configuration_profile_projects {
        project_id: bigint
        profile_id: bigint
    }

    class security_scan_configuration_profiles {
        id: bigint,
        ...
    }

    note for security_configuration_profile_exclusions "migration from project_security_exclusions"
    class security_configuration_profile_exclusions {
        id: bigint
        profile_id: bigint
    }

    class security_scans {
        id: bigint
        created_at: timestamp
        updated_at: timestamp
        project_id: bigint
        scan_type: text
        status: smallint
        pipeline_id: bigint (nullable)
        build_id: bigint (nullable)
    }

    projects <-- namespaces : has_many
    projects --> security_scans : has_many

    security_scan_configuration_profiles --> security_scans : has_many
    security_scan_configuration_profiles --> security_configuration_profile_exclusions : has_many
    security_scan_configuration_profile_projects <-- projects : has_many
    security_scan_configuration_profile_projects <-- security_scan_configuration_profiles : has_many
    namespaces --> security_scan_configuration_profiles : has_many