GitHub
This guide walks you through setting up Endura pipeline security for GitHub Actions. You will learn how to run the Runtime Sensor on both GitHub-hosted and self-hosted runners, configure the GitHub integration for automatic pipeline discovery, instrument your GitHub Actions workflows to use the Sensor, and apply security policies to your pipelines.
GitHub-Hosted and Self-Hosted Runners Are Both Supported
The Runtime Sensor works with both runner types. The only difference is where the Sensor is installed:
- Self-hosted runners: Install the Sensor once on the runner host. Your workflows then call
endura job startandendura job stopto bracket each build. - GitHub-hosted runners: Because these runners are ephemeral, install and start the Sensor as steps within the workflow itself, then call
endura job startandendura job stop.
Both approaches are covered in Configure GitHub Actions Workflows.
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 GitHub organization for creating access tokens and configuring workflows.
- For self-hosted runners: root or sudo access to the runner hosts (for installing the Runtime Sensor).
- For GitHub-hosted runners: an Endura license key and Sensor token stored as encrypted repository or organization secrets (used to install the Sensor at workflow runtime).
Configure the GitHub Integration
The GitHub integration enables Team Server to discover and ingest your GitHub repositories as pipelines. This section covers creating a GitHub personal access token and configuring the integration in Team Server.
Create a GitHub Personal Access Token
GitHub personal access tokens allow Team Server to authenticate with the GitHub API to discover repositories and workflow runs.
Use a Dedicated Service Account
For production deployments, create a dedicated machine (service) account in GitHub specifically for the Team Server integration rather than using a personal administrator account. This account should have:
- Read-only access to the organizations and repositories you want to monitor
- A clear naming convention (e.g.,
svc-endura-teamserver)
Using a service account improves security, simplifies auditing, and ensures the integration continues working when individual team members leave the organization.
Setup Instructions:
- Log in to GitHub as the account that will own the integration token
- Click your profile photo in the top-right corner and click Settings
- In the left sidebar, click Developer settings
- Click Personal access tokens, then choose one of the following:
- Fine-grained tokens (recommended): grant the token Read-only access to the relevant organizations and repositories, with the Actions and Metadata repository permissions set to Read-only
- Tokens (classic): select the
reposcope (for private repositories) and theread:orgscope so Team Server can enumerate organizations and repositories
- Set an expiration appropriate to your security requirements, and document a token rotation schedule
- Click Generate token
- Copy the token value immediately; it will not be shown again
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.
If your organization enforces SAML single sign-on, you may also need to authorize the token for SSO before it can access organization resources.
Add the Integration in Team Server
With the GitHub personal access token created, configure the integration in Team Server.
Setup Instructions:
- Log in to Team Server
- Click Integrations in the main navigation menu
- Click GitHub under the Discover sub-navigation menu
- Click Get Started (if no GitHub integration exists) or Create (if you already have one or more GitHub integrations configured)
- Configure the integration:
- URL: Enter the base URL of your GitHub instance. Use
https://github.comfor GitHub.com, or your server URL for GitHub Enterprise Server (e.g.,https://github.example.com) - Token: Paste the personal access token you created in GitHub
- URL: Enter the base URL of your GitHub instance. Use
- Click Test to verify the connection to GitHub
- After a successful test, the Organizations field populates with the organizations your token can access. Select one or more organizations to monitor
- Click Save to create the integration
Selecting Organizations
The Organizations 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 organization must be selected. Team Server discovers and ingests the repositories within the organizations you choose.
Troubleshooting Connection Issues
If the connection test fails, check the following:
- Verify the GitHub URL is correct and accessible from the Team Server host
- Confirm the access token has not expired and (if applicable) is authorized for SSO
- Confirm the token has the required read permissions for organizations and repositories
- Check for any network restrictions or firewalls between Team Server and GitHub
- 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 repositories in the selected organizations as pipelines. View the discovered pipelines by clicking Pipelines in the main navigation menu.
Multiple GitHub Instances
If your organization uses both GitHub.com and one or more GitHub Enterprise Server 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 GitHub repositories. To automatically discover new repositories and workflow runs on an ongoing basis, configure the scheduled discovery jobs in your Team Server configuration.
Add the discover_github_pipelines and discover_github_builds jobs to the scheduler section of your Team Server configuration file (config/production.yaml):
scheduler:
jobs:
discover_github_pipelines:
run: "discover_github_pipelines"
schedule: "0 0 * * * * *"
discover_github_builds:
run: "discover_github_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 GitHub discovery jobs alongside the required Team Server jobs:
scheduler:
output: stdout
jobs:
discover_github_pipelines:
run: "discover_github_pipelines"
schedule: "0 0 * * * * *"
discover_github_builds:
run: "discover_github_builds"
schedule: "0 */15 * * * * *"
calculate_statistics:
run: "calculate_statistics"
schedule: "0 0 5 * * * *"
update_status:
run: "update_status"
schedule: "0 */5 * * * * *"| Job | Purpose |
|---|---|
discover_github_pipelines | Discovers new GitHub repositories and ingests them as pipelines |
discover_github_builds | Discovers new workflow runs from configured GitHub 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-Hosted Runners
If your workflows run on self-hosted runners, install the Runtime Sensor once on each runner host. The Sensor monitors build execution and enforces security policies at runtime. If you use GitHub-hosted runners, skip this section; the Sensor is installed within the workflow instead (see GitHub-Hosted Runners).
Installation Overview
Install the Runtime Sensor on each self-hosted runner host:
- Identify all hosts running self-hosted runners that execute the workflows 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-hosted 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 Groups
GitHub organizes self-hosted runners into runner groups for access control and workload distribution. When deploying the Runtime Sensor:
- Identify all runner groups that run workflows you want to monitor
- Install the Sensor on every runner host within those groups
- When adding new runners to a group, include Sensor installation in your runner provisioning process
For auto-scaling or ephemeral self-hosted runners (e.g., runners provisioned on demand), bake Sensor installation into the runner image or provisioning scripts so new runners automatically receive the Sensor.
Configure GitHub Actions Workflows
With the integration configured, instrument your GitHub Actions workflows to communicate with the Sensor. Choose the pattern that matches your runner type.
Self-Hosted Runners
When the Sensor is already installed on the runner host, your workflow only needs to bracket the build with endura job start and endura job stop. Add the start command as the first step and the stop command as a final step guarded with if: always() so it runs even when a preceding step fails.
jobs:
build:
runs-on: [self-hosted, linux]
steps:
- name: Start Endura Job
run: endura job start
# ... your existing build steps ...
- uses: actions/checkout@v4
- name: Build
run: make build
- name: Stop Endura Job
if: always()
run: endura job stopKey points:
runs-ontargets your self-hosted runners (using a label such asself-hostedand any additional labels you assign).- The Start Endura Job step must be the first step in the job.
- The Stop Endura Job step must be the last step and use
if: always()so it runs on both successful and failed jobs.
GitHub-Hosted Runners
GitHub-hosted runners are ephemeral, so the Sensor is installed and started inside the workflow run. Add a step that installs and starts the Sensor and then starts the Endura job, and a final step (guarded with if: always()) that stops the job and the Sensor.
name: CI
on:
push:
branches:
- main
workflow_dispatch:
defaults:
run:
shell: bash
env:
ENDURA_TEAM_SERVER: https://teamserver.example.com
ENDURA_BATCHER_AUTOFLUSH: true
jobs:
build:
name: Build
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Start Runtime Sensor and Job
run: |
curl -sSf https://repo.endurasecurity.com/install/endura-sensor/testing.sh | sudo -E sh
sudo -E endura sensor start -d
echo "started endura sensor: $(sudo -E endura sensor status)"
ENDURA_JOB_ID=$(endura job start)
echo "started endura job with id ${ENDURA_JOB_ID}"
env:
ENDURA_LICENSE_KEY: ${{ secrets.ENDURA_LICENSE_KEY }}
ENDURA_SENSOR_TOKEN: ${{ secrets.ENDURA_SENSOR_TOKEN }}
- name: Checkout Code
uses: actions/checkout@v4
# ... your existing build steps ...
- name: Build
run: make build
- name: Stop Endura Job and Sensor
if: always()
run: |
endura job stop
sudo -E endura sensor stopThe environment variables configure the Sensor that the workflow 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 an encrypted secret. |
ENDURA_SENSOR_TOKEN | The Sensor enrollment token. Store as an encrypted secret. |
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 GitHub Actions encrypted secrets (at the repository or organization level), never as plaintext in the workflow file. Scope each job’s permissions to the minimum required (for example, contents: read) to limit the blast radius if a build is compromised.
Always Run the Stop Step
The if: always() condition is critical. It ensures the Sensor receives the stop signal (and, on GitHub-hosted runners, that the Sensor is stopped cleanly) even when build steps fail or the job is cancelled, allowing proper cleanup and policy evaluation.
Verify the Configuration
Run a workflow to verify your configuration is working correctly.
Setup Instructions:
- Commit and push the instrumented workflow, or trigger it manually from the Actions tab in GitHub
- Wait for the workflow run to complete
- Log in to Team Server
- Click Pipelines in the main navigation menu
- Locate your repository 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 workflow run you just triggered
If the build appears in Team Server, your configuration is working correctly. Proceed to create and assign security policies.
Standardize Workflows at Scale
For organizations managing many repositories, adding the Endura steps to every workflow individually does not scale. GitHub provides several mechanisms to centralize and reuse workflow logic. Each works with both runner types: encapsulate the self-hosted or GitHub-hosted instrumentation shown above so individual repositories adopt it with a single reference.
Composite Actions
Package the Endura start and stop logic as a composite action published in a central repository, then reference it from any workflow:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Start Endura Job
uses: your-org/endura-actions/start@<commit-sha>
# ... your existing build steps ...
- name: Stop Endura Job
if: always()
uses: your-org/endura-actions/stop@<commit-sha>Maintaining the action in one place lets you update the instrumentation for all consuming repositories by publishing a new version.
Pin Actions to a Commit SHA
For supply chain security, pin third-party and internal actions to a full-length commit SHA (e.g., your-org/endura-actions/start@a1b2c3d...) rather than a mutable tag or branch. A SHA cannot be moved to point at altered code, so it protects you from a compromised or retagged action. See GitHub’s security hardening for GitHub Actions for details.
Reusable Workflows
Define a reusable workflow (on: workflow_call) in a central repository that wraps build work with the Endura start and stop steps. Repositories then call it with a single uses: reference, inheriting the instrumentation automatically.
Organization-Wide Distribution and Enforcement
- Starter workflows: Publish starter workflows in your organization’s
.githubrepository so new repositories can adopt an Endura-instrumented workflow with one click. - Required workflows: Use required workflows / repository rulesets to enforce an Endura-instrumented workflow across all repositories in the organization. This guarantees the Sensor instrumentation runs regardless of each repository’s own workflow definitions.
Tier-Dependent Features
Required workflows and some organization-level controls depend on your GitHub plan (organization or enterprise tier). Composite actions, reusable workflows, and starter workflows are available across plans and provide a strong baseline for scaled adoption.
Container-Based Jobs on Self-Hosted Runners
On self-hosted runners, GitHub Actions can run jobs inside a container. When using container-based jobs, 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 self-hosted 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
Mount the Sensor’s communication socket using the container options:
jobs:
build:
runs-on: [self-hosted, linux]
container:
image: node:20
options: --volume /run/endura/sensor.sock:/run/endura/sensor.sock
steps:
- name: Start Endura Job
run: |
curl -sSf https://repo.endurasecurity.com/install/endura-sensor/testing.sh | sh
endura job start
# ... your existing build steps ...
- name: Stop Endura Job
if: always()
run: endura job stopThe installation script installs the Endura CLI inside the container, 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-Job Workflows
GitHub Actions workflows can contain multiple jobs, including jobs linked with needs: dependencies. Each job runs in its own runner context. When instrumenting these workflows with Endura:
- Add the Endura instrumentation to each job that performs build work
- Each job operates independently from Endura’s perspective and can have its own security policy
- Create separate policies for jobs that perform different types of work (e.g., build vs. test vs. deploy)
- When deriving policies, run the full workflow 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 workflow in GitHub that exercises your pipeline’s typical behavior
- Open the completed workflow run from the Actions tab in GitHub
- Expand the step that runs
endura job stopin the job logs - 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., “GitHub - my-org/my-repo Build Policy”)
- Description: Enter a brief description (e.g., “Security policy for the my-repo CI/CD pipeline”)
- Version: Enter
1.0 - Policy: Paste the derived policy you copied from the GitHub workflow 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 GitHub 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 repository 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 workflows with the policy in observe mode
- After each run, check for violations in Team Server:
- Navigate to Pipelines and select your repository
- 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 GitHub 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 GitHub workflow run fails
- Violation details are reported to Team Server for review
- Notifications are sent via configured channels (e.g., Slack)
Next Steps
With GitHub pipeline security configured, consider the following:
- Configure additional pipelines: Apply the same process to other repositories and workflows
- 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