Skip to content

GitLab

This guide walks you through setting up Endura pipeline security for GitLab CI/CD. You will learn how to run the Runtime Sensor on both self-managed and GitLab-managed runners, configure the GitLab integration for automatic pipeline discovery, instrument your GitLab CI/CD pipelines to use the Sensor, and apply security policies to your pipelines.

Self-Managed and GitLab-Managed Runners Are Both Supported

The Runtime Sensor works with both runner types. The only difference is where the Sensor is installed:

  • Self-managed runners: Install the Sensor once on the runner host. Your pipelines then call endura job start and endura job stop to bracket each job.
  • GitLab-managed runners (GitLab.com SaaS / hosted runners): Because these runners are ephemeral, install and start the Sensor as part of the job using before_script, then call endura job start and endura job stop.

Both approaches are covered in Configure GitLab CI/CD Pipelines.

Prerequisites

Before proceeding, ensure you have:

  • Team Server installed and running with valid credentials for accessing the web interface. If you have not deployed Team Server yet, see the Team Server documentation for deployment options.
  • Administrative access to your GitLab groups for creating access tokens and configuring CI/CD pipelines.
  • For self-managed runners: root or sudo access to the runner hosts (for installing the Runtime Sensor).
  • For GitLab-managed runners: an Endura license key and Sensor token stored as masked CI/CD variables (used to install the Sensor at job runtime).

Configure the GitLab Integration

The GitLab integration enables Team Server to discover and ingest your GitLab projects as pipelines. This section covers creating a GitLab access token and configuring the integration in Team Server.

Create a GitLab Access Token

GitLab access tokens allow Team Server to authenticate with the GitLab API to discover projects and jobs.

Use a Dedicated Service Account or Group Token

For production deployments, use a dedicated service account or a group access token for the Team Server integration rather than a personal administrator account. The token should have:

  • Read-only access to the groups and projects you want to monitor
  • The read_api scope (Team Server only queries the API; it does not modify GitLab resources)
  • A clear naming convention (e.g., svc-endura-teamserver)

Using a service account or group token improves security, simplifies auditing, and ensures the integration continues working when individual team members leave the organization.

Setup Instructions:

  1. Log in to GitLab
  2. Create the token using one of the following:
    • Personal access token: Click your avatar > Edit profile > Access tokens
    • Group access token (recommended): Navigate to the group, then Settings > Access tokens
  3. Click Add new token
  4. Configure the token:
    • Token name: Enter a descriptive name (e.g., “Endura Team Server”)
    • Expiration date: Select an appropriate expiration based on your security requirements, and document a token rotation schedule
    • Scopes: Select read_api
  5. Click Create personal access token (or Create group access token)
  6. Copy the token value immediately; it will not be shown again (GitLab tokens begin with glpat-)

Store the Token Securely

The token value is displayed only once upon creation. Copy it immediately and store it in a secure location such as a password manager or secrets vault. If you lose the token, you will need to create a new one.

Add the Integration in Team Server

With the GitLab access token created, configure the integration in Team Server.

Setup Instructions:

  1. Log in to Team Server
  2. Click Integrations in the main navigation menu
  3. Click GitLab under the Discover sub-navigation menu
  4. Click Get Started (if no GitLab integration exists) or Create (if you already have one or more GitLab integrations configured)
  5. Configure the integration:
    • URL: Enter the base URL of your GitLab instance. Use https://gitlab.com for GitLab.com, or your server URL for a self-managed instance (e.g., https://gitlab.example.com)
    • Token: Paste the access token you created in GitLab
  6. Click Test to verify the connection to GitLab
  7. After a successful test, the Groups field populates with the groups your token can access. Select one or more groups to monitor
  8. Click Save to create the integration

Selecting Groups

The Groups field is a searchable multi-select that loads automatically once you have entered a valid URL and token and the connection test succeeds. At least one group must be selected. Team Server discovers and ingests the projects within the groups you choose.

Troubleshooting Connection Issues

If the connection test fails, check the following:

  • Verify the GitLab URL is correct and accessible from the Team Server host
  • Confirm the access token has not expired and has the read_api scope
  • Check for any network restrictions or firewalls between Team Server and GitLab
  • Review error messages displayed as toast notifications
  • Examine the Application Logs under Administration in the main navigation for detailed error information

Once the integration is created, Team Server immediately begins discovering and ingesting the projects in the selected groups as pipelines. View the discovered pipelines by clicking Pipelines in the main navigation menu.

Multiple GitLab Instances

If your organization uses both GitLab.com and one or more self-managed GitLab instances, create a separate integration for each. All discovered pipelines from all instances will appear in the unified Pipelines view in Team Server.

Enable Scheduled Discovery

The initial integration setup performs a one-time discovery of GitLab projects. To automatically discover new projects and jobs on an ongoing basis, configure the scheduled discovery jobs in your Team Server configuration.

Add the discover_gitlab_pipelines and discover_gitlab_builds jobs to the scheduler section of your Team Server configuration file (config/production.yaml):

scheduler:
  jobs:
    discover_gitlab_pipelines:
      run: "discover_gitlab_pipelines"
      schedule: "0 0 * * * * *"
    discover_gitlab_builds:
      run: "discover_gitlab_builds"
      schedule: "0 */15 * * * * *"

The schedule field uses a 7-field cron format: second minute hour day month day-of-week year. The examples above run pipeline discovery every hour and build discovery every 15 minutes.

A complete scheduler configuration including the GitLab discovery jobs alongside the required Team Server jobs:

scheduler:
  output: stdout
  jobs:
    discover_gitlab_pipelines:
      run: "discover_gitlab_pipelines"
      schedule: "0 0 * * * * *"
    discover_gitlab_builds:
      run: "discover_gitlab_builds"
      schedule: "0 */15 * * * * *"
    calculate_statistics:
      run: "calculate_statistics"
      schedule: "0 0 5 * * * *"
    update_status:
      run: "update_status"
      schedule: "0 */5 * * * * *"
JobPurpose
discover_gitlab_pipelinesDiscovers new GitLab projects and ingests them as pipelines
discover_gitlab_buildsDiscovers new jobs from configured GitLab integrations
calculate_statisticsComputes security metrics for dashboards (required)
update_statusRefreshes status for monitored resources (required)

After updating the configuration, restart Team Server for the changes to take effect. For restart procedures specific to your deployment method, see:

For additional configuration details, see the Team Server Configuration Guide.


Install the Runtime Sensor on Self-Managed Runners

If your jobs run on self-managed runners, install the Runtime Sensor once on each runner host. The Sensor monitors build execution and enforces security policies at runtime. If you use GitLab-managed runners, skip this section; the Sensor is installed within the job instead (see GitLab-Managed Runners).

Installation Overview

Install the Runtime Sensor on each self-managed GitLab Runner host:

  1. Identify all hosts running GitLab Runners that execute the jobs you want to monitor
  2. Install the appropriate Runtime Sensor package for each host’s Linux distribution
  3. Configure the Sensor to communicate with Team Server

For detailed installation instructions specific to your Linux distribution, see the Runtime Sensor documentation.

Sensor Deployment Best Practices

  • Install the Sensor on all self-managed GitLab Runner hosts to ensure consistent policy enforcement across your build infrastructure
  • Use configuration management tools (Ansible, Puppet, Chef) for deploying the Sensor at scale
  • Verify network connectivity from each Runner host to Team Server on port 443

Runner Tags

GitLab uses runner tags to control which runners execute which jobs. When deploying the Runtime Sensor:

  • Identify the runners (and their tags) that run jobs you want to monitor
  • Install the Sensor on every host backing those runners
  • Ensure your jobs target tagged runners that have the Sensor installed (using the tags: keyword in your .gitlab-ci.yml)

For auto-scaling runner fleets, bake Sensor installation into the runner image or provisioning scripts so new runner hosts automatically receive the Sensor.


Configure GitLab CI/CD Pipelines

With the integration configured, instrument your GitLab CI/CD pipelines to communicate with the Sensor. GitLab makes this straightforward: a top-level default section with before_script and after_script applies to every job, and after_script runs even when a job fails. Choose the pattern that matches your runner type.

Self-Managed Runners

When the Sensor is already installed on the runner host, your pipeline only needs to bracket each job with endura job start and endura job stop:

default:
  tags:
    - endura          # target a runner with the Sensor installed
  before_script:
    - endura job start
  after_script:
    - endura job stop

build:
  script:
    - make build

Key points:

  • before_script runs endura job start before each job’s script.
  • after_script runs endura job stop after each job’s script, including when the job’s script fails or times out.
  • The tags keyword targets a runner that has the Sensor installed.

GitLab-Managed Runners

GitLab-managed runners are ephemeral, so the Sensor is installed and started inside the job. Install and start the Sensor in before_script, then start the Endura job; in after_script, stop the Endura job and the Sensor:

variables:
  ENDURA_TEAM_SERVER: "https://teamserver.example.com"
  ENDURA_BATCHER_AUTOFLUSH: "true"

default:
  before_script:
    - curl -sSf https://repo.endurasecurity.com/install/endura-sensor/testing.sh | sudo -E sh
    - sudo -E endura sensor start -d
    - endura job start
  after_script:
    - endura job stop
    - sudo -E endura sensor stop

build:
  script:
    - make build

The variables configure the Sensor that the job installs at runtime:

VariablePurpose
ENDURA_TEAM_SERVERBase URL of your Team Server (where telemetry is reported)
ENDURA_LICENSE_KEYYour Endura license key. Store as a masked, protected CI/CD variable.
ENDURA_SENSOR_TOKENThe Sensor enrollment token. Store as a masked, protected CI/CD variable.
ENDURA_BATCHER_AUTOFLUSHSet to true so telemetry is flushed immediately. Recommended for ephemeral runners, which are destroyed as soon as the job ends.

These are the variables most relevant to CI/CD instrumentation. For the complete list of sensor environment variables and their defaults, see the Runtime Sensor Configuration reference.

Protect Sensor Credentials

Store ENDURA_LICENSE_KEY and ENDURA_SENSOR_TOKEN as masked and protected CI/CD variables under Settings > CI/CD > Variables (at the project or group level), never as plaintext in .gitlab-ci.yml. Masking keeps the values out of job logs, and protecting them restricts their use to protected branches and tags.

sudo and Privileges

The example uses sudo to install and control the Sensor. If your runner already executes jobs as root, you can omit sudo. The Sensor requires privileged access to load its kernel instrumentation, so the job environment must allow it.

after_script Always Runs

GitLab executes after_script even when the job’s script fails or the job is cancelled. Placing endura job stop (and, on GitLab-managed runners, the Sensor stop) in after_script ensures the Sensor receives the stop signal on both successful and failed jobs, allowing proper cleanup and policy evaluation.

Jobs That Override before_script/after_script

A job that defines its own before_script or after_script overrides the values from default. If you have such jobs, re-add the Endura commands in those jobs, or use extends/YAML anchors to merge them in.

Verify the Configuration

Run a pipeline to verify your configuration is working correctly.

Setup Instructions:

  1. Commit and push the instrumented .gitlab-ci.yml, or trigger a pipeline manually from Build > Pipelines in GitLab
  2. Wait for the pipeline to complete
  3. Log in to Team Server
  4. Click Pipelines in the main navigation menu
  5. Locate your project in the pipeline list
  6. Click the Edit (pencil icon) button for the pipeline
  7. Click the Builds tab
  8. Verify that a new build entry appears for the job you just triggered

If the build appears in Team Server, your configuration is working correctly. Proceed to create and assign security policies.

Standardize Pipelines at Scale

For organizations managing many projects, adding the Endura instrumentation to every .gitlab-ci.yml individually does not scale. GitLab provides several mechanisms to centralize and reuse CI/CD configuration. Each works with both runner types: define the self-managed or GitLab-managed instrumentation shown above once, and projects adopt it with a single reference.

Central CI/CD Templates with include

Define the Endura instrumentation once in a central project, then pull it into any project’s .gitlab-ci.yml with include:

# In your project's .gitlab-ci.yml
include:
  - project: 'platform/ci-templates'
    ref: main
    file: '/endura.yml'

build:
  script:
    - make build

The central endura.yml defines the default before_script/after_script for your runner type. Projects opt in with a single include line, and updates to the central template propagate to all consumers. Use extends to share and merge job-level configuration where finer control is required.

Compliance Framework Pipelines

For organization-wide enforcement, GitLab Ultimate supports compliance framework pipelines. A compliance pipeline configuration is injected into every project labeled with the compliance framework, regardless of the project’s own .gitlab-ci.yml. This guarantees the Endura start and stop steps run for all in-scope projects, even if a project author modifies or removes their pipeline configuration.

Tier-Dependent Features

Compliance framework pipelines require GitLab Ultimate. The include and extends mechanisms are available across all GitLab tiers and provide a strong baseline for scaled adoption.

Container-Based Jobs (Docker Executor)

When a self-managed GitLab Runner uses the Docker executor, jobs run inside containers, and the Sensor (installed on the host) must be reachable from inside the container.

Requirements for Container Jobs

For container-based jobs to work with Endura:

  1. The Runtime Sensor must be installed on the GitLab Runner host (the machine running the runner and Docker daemon)
  2. The Sensor socket must be mounted into the job container to enable communication between the containerized job and the host Sensor
  3. The Endura CLI must be installed inside the container at the start of each job

Configure the Container Socket Mount

For the Docker executor, mount the Sensor’s communication socket by adding a volume to the runner’s config.toml:

[[runners]]
  [runners.docker]
    volumes = ["/run/endura/sensor.sock:/run/endura/sensor.sock"]

After editing config.toml, restart the GitLab Runner service so the change takes effect.

Install the Endura CLI in the Container

For container-based jobs, install the Endura CLI inside the container before signaling the job start. Update the before_script so it installs the CLI first:

default:
  before_script:
    - curl -sSf https://repo.endurasecurity.com/install/endura-sensor/testing.sh | sh
    - endura job start
  after_script:
    - endura job stop

The installation script installs the Endura CLI, which then communicates with the Runtime Sensor on the host via the mounted socket.

Socket Mount is Required

Without the /run/endura/sensor.sock mount, the endura job start and endura job stop commands will fail to communicate with the Runtime Sensor. The Sensor runs on the Runner host, not inside the container; the socket mount bridges this gap.

Multi-Stage and Child Pipelines

GitLab pipelines can contain multiple stages and jobs, as well as parent-child pipelines. Each job runs in its own runner context. When instrumenting these pipelines with Endura:

  • The default before_script/after_script instruments every job in the pipeline automatically
  • For child pipelines defined in separate configuration files, include the same Endura default configuration (via include) so child jobs are also instrumented
  • Each job operates independently from Endura’s perspective and can have its own security policy
  • When deriving policies, run the full pipeline so that every job is exercised

Create and Assign Security Policies

With your builds reporting to Team Server, you can now create security policies tailored to your pipeline’s behavior. Endura’s derive mode makes this process straightforward by automatically generating a policy based on observed runtime behavior.

Understand Policy Modes

Security policies operate in one of three modes:

ModeBehavior
deriveMonitor pipeline behavior and generate a baseline policy (initial setup)
observeLog policy violations without taking action (testing/refinement)
enforceBlock unauthorized operations and fail builds on violations (production)

The recommended workflow is: derive then observe then enforce.

Derive a Baseline Policy

When the Runtime Sensor runs without an assigned policy (or with a policy in derive mode), it monitors all runtime behavior and outputs a derived policy when the build completes.

Setup Instructions:

  1. Run a pipeline in GitLab that exercises your pipeline’s typical behavior
  2. Open the completed job from Build > Jobs (or the pipeline view) in GitLab
  3. In the job log, locate the after_script output where endura job stop ran
  4. Look for the text # ENDURA DERIVED POLICY in the logs
  5. Copy the entire policy that follows this marker; this is your baseline policy derived from actual runtime behavior

The derived policy contains rules based on what your pipeline actually did during execution: processes spawned, files accessed, network connections made, and more.

Create the Policy in Team Server

With the derived policy copied, create a formal policy in Team Server.

Setup Instructions:

  1. Log in to Team Server
  2. Click Policies in the main navigation menu
  3. Click the Create button
  4. Fill in the policy details:
    • Name: Enter a descriptive name (e.g., “GitLab - my-group/my-project Build Policy”)
    • Description: Enter a brief description (e.g., “Security policy for the my-project CI/CD pipeline”)
    • Version: Enter 1.0
    • Policy: Paste the derived policy you copied from the GitLab job log
  5. Review the policy and make any necessary adjustments (see the section below on refining policies)
  6. Change the mode from derive to observe
  7. Click Create

Assign the Policy to Your Pipeline

Link the policy to your GitLab pipeline so the Sensor enforces it during builds.

Setup Instructions:

  1. In Team Server, navigate to Policies in the main navigation menu
  2. Locate your policy in the policy list
  3. Click the Assign Policy button (link icon) in the Actions column
  4. Search for your project by name
  5. Select the pipeline by clicking its checkbox
  6. Click Assign to 1 Pipeline (or the appropriate count if assigning to multiple pipelines)

Refine the Policy

Derived policies capture exact behavior, which may be overly specific. Before moving to enforce mode, review and refine the policy:

Common refinements:

  • Consolidate file paths: If a process writes many files to a directory (e.g., /home/user/workspace/build/), replace individual file entries with a directory pattern using wildcards
  • Remove ephemeral paths: Build artifacts in temporary directories may have unique names per build. Use patterns like /tmp/* instead of specific paths
  • Group similar operations: Multiple similar rules can often be consolidated into more general patterns
  • Remove redundant entries: The derived policy may include duplicate or overlapping rules

Testing in observe mode:

  1. Run several pipelines with the policy in observe mode
  2. After each run, check for violations in Team Server:
    • Navigate to Pipelines and select your project
    • Click Edit (pencil icon)
    • Click the Builds tab and select the latest build
    • Click Violations to see any policy violations
  3. For each violation, determine whether it represents:
    • Legitimate behavior: Update the policy to allow it
    • Unexpected behavior: Investigate the cause before deciding
  4. Iterate until builds complete without unexpected violations

Enable Policy Enforcement

Once your policy is refined and builds run cleanly in observe mode, enable enforcement.

Setup Instructions:

  1. In Team Server, click Policies in the main navigation menu
  2. Locate your GitLab policy
  3. Click the Edit Policy (pencil icon) button
  4. Update the policy:
    • Change Version from 1.0 to 1.1 (or your next version number)
    • Change mode from observe to enforce
  5. Click Save
  6. Enter a description of your change when prompted (e.g., “Enabled enforcement after observe mode testing”). Team Server maintains policy version history for audit purposes
  7. Click Save to confirm

Enforcement Behavior

With the policy in enforce mode, the Runtime Sensor will block unauthorized operations and fail builds when violations occur. Ensure you have thoroughly tested your policy in observe mode before enabling enforcement.

When a violation occurs in enforce mode:

  • The Sensor takes immediate action (blocks the operation or terminates the offending process)
  • The GitLab job fails
  • Violation details are reported to Team Server for review
  • Notifications are sent via configured channels (e.g., Slack)

Next Steps

With GitLab pipeline security configured, consider the following:

  • Configure additional pipelines: Apply the same process to other GitLab projects and groups
  • Explore policy capabilities: See the Security Policies documentation for detailed information on policy syntax, advanced rules, and best practices
  • Set up notifications: Configure Slack integration to receive real-time alerts on policy violations
  • Review audit history: Use Team Server’s policy version history to track changes and maintain compliance documentation