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 startandendura job stopto 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 callendura job startandendura 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_apiscope (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:
- Log in to GitLab
- 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
- Click Add new token
- 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
- Click Create personal access token (or Create group access token)
- 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:
- Log in to Team Server
- Click Integrations in the main navigation menu
- Click GitLab under the Discover sub-navigation menu
- Click Get Started (if no GitLab integration exists) or Create (if you already have one or more GitLab integrations configured)
- Configure the integration:
- URL: Enter the base URL of your GitLab instance. Use
https://gitlab.comfor 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
- URL: Enter the base URL of your GitLab instance. Use
- Click Test to verify the connection to GitLab
- After a successful test, the Groups field populates with the groups your token can access. Select one or more groups to monitor
- 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_apiscope - 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 * * * * *"| Job | Purpose |
|---|---|
discover_gitlab_pipelines | Discovers new GitLab projects and ingests them as pipelines |
discover_gitlab_builds | Discovers new jobs from configured GitLab integrations |
calculate_statistics | Computes security metrics for dashboards (required) |
update_status | Refreshes 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:
- Identify all hosts running GitLab Runners that execute the jobs you want to monitor
- Install the appropriate Runtime Sensor package for each host’s Linux distribution
- 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 buildKey points:
before_scriptrunsendura job startbefore each job’sscript.after_scriptrunsendura job stopafter each job’sscript, including when the job’sscriptfails or times out.- The
tagskeyword 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 buildThe variables configure the Sensor that the job installs at runtime:
| Variable | Purpose |
|---|---|
ENDURA_TEAM_SERVER | Base URL of your Team Server (where telemetry is reported) |
ENDURA_LICENSE_KEY | Your Endura license key. Store as a masked, protected CI/CD variable. |
ENDURA_SENSOR_TOKEN | The Sensor enrollment token. Store as a masked, protected CI/CD variable. |
ENDURA_BATCHER_AUTOFLUSH | Set 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:
- Commit and push the instrumented
.gitlab-ci.yml, or trigger a pipeline manually from Build > Pipelines in GitLab - Wait for the pipeline to complete
- Log in to Team Server
- Click Pipelines in the main navigation menu
- Locate your project in the pipeline list
- Click the Edit (pencil icon) button for the pipeline
- Click the Builds tab
- 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 buildThe 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:
- The Runtime Sensor must be installed on the GitLab Runner host (the machine running the runner and Docker daemon)
- The Sensor socket must be mounted into the job container to enable communication between the containerized job and the host Sensor
- 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 stopThe 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
defaultbefore_script/after_scriptinstruments every job in the pipeline automatically - For child pipelines defined in separate configuration files, include the same Endura
defaultconfiguration (viainclude) 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:
| Mode | Behavior |
|---|---|
derive | Monitor pipeline behavior and generate a baseline policy (initial setup) |
observe | Log policy violations without taking action (testing/refinement) |
enforce | Block 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:
- Run a pipeline in GitLab that exercises your pipeline’s typical behavior
- Open the completed job from Build > Jobs (or the pipeline view) in GitLab
- In the job log, locate the
after_scriptoutput whereendura job stopran - Look for the text
# ENDURA DERIVED POLICYin the logs - 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:
- Log in to Team Server
- Click Policies in the main navigation menu
- Click the Create button
- 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
- Review the policy and make any necessary adjustments (see the section below on refining policies)
- Change the mode from
derivetoobserve - Click Create
Assign the Policy to Your Pipeline
Link the policy to your GitLab pipeline so the Sensor enforces it during builds.
Setup Instructions:
- In Team Server, navigate to Policies in the main navigation menu
- Locate your policy in the policy list
- Click the Assign Policy button (link icon) in the Actions column
- Search for your project by name
- Select the pipeline by clicking its checkbox
- 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:
- Run several pipelines with the policy in observe mode
- 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
- For each violation, determine whether it represents:
- Legitimate behavior: Update the policy to allow it
- Unexpected behavior: Investigate the cause before deciding
- 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:
- In Team Server, click Policies in the main navigation menu
- Locate your GitLab policy
- Click the Edit Policy (pencil icon) button
- Update the policy:
- Change Version from
1.0to1.1(or your next version number) - Change mode from
observetoenforce
- Change Version from
- Click Save
- 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
- 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