Enforce an egress policy across your organization
Define an egress policy in the control plane and have it override what individual workflow files configure.
Before you begin
- Admin access to the organization in Bullfrog. See Roles and permissions.
- An API token configured as the
api-tokeninput on the jobs you want to govern. A job without a token never asks for a policy. See Manage API tokens. - Bullfrog GitHub Action v0.11.0 on those jobs
Read How policies reach a job before you write a policy that blocks. A policy replaces a job's own configuration rather than merging with it, and every matching policy contributes.
Step 1: Start in audit mode, organization-wide
Give yourself a baseline before you enforce anything.
- In the left navigation, select Policies.
- Select + New policy.
- Enter a Name, such as
org-baseline. - Set all three scope fields to
*: Repo, Workflow file, and Job. - Leave Egress policy as Audit.
- Select Create policy.
Every job with a token now runs in audit mode regardless of what its workflow file says, and reports what it reached.
Step 2: Collect what your jobs actually connect to
Let the policy run for a few days, then open Unauthorized Connections to see the destinations your workflows reach that nothing allows yet. See Investigate unauthorized connections.
Step 3: Narrow the scope to a job you're ready to enforce
Enforce one job before you enforce all of them. Pick a job whose network behavior you understand, such as a release or deploy job.
- Select + New policy.
- Name it after the job, such as
release-publish. - Set the scope:
- Repo: the repository name only, such as
web-app. Notmy-org/web-app. - Workflow file: the workflow's path, such as
.github/workflows/release.yml. - Job: the job's id, meaning the key under
jobs:in the workflow file, such aspublish. Not the job's displayname.
- Repo: the repository name only, such as
- Set Egress policy to Block.
- Enter the destinations that job needs under Allowed domains and Allowed IPs, one per line.
- Leave DNS policy at Allowed domains only and Sudo policy at Disable, which are the defaults for block mode.
- Select Create policy.
All three scope fields accept * as a wildcard, matching any sequence of characters, and matching is case-insensitive. web-* matches every repository whose name starts with web-, and .github/workflows/*.yml matches every workflow file in the standard location.
Your org-baseline policy still matches this job. Both apply: the allowlists are combined, and Block wins over Audit. That's the intent, but it means the job's allowlist is the union of both policies' entries.
Step 4: Verify the policy applied
Trigger the job, then open Workflow Runs and select the run.
- Connections now carry a Blocked or Authorized status rather than Unauthorized.
- If the job's workflow file sets different inputs than your policy, the policy's values are the ones that took effect.
If the job's results look unchanged, the policy didn't reach it. Check that the job passes api-token, and that all three scope fields match. A Job field holding the display name instead of the job id is the most common miss.
Step 5: Widen enforcement
Repeat step 3 for each job you're ready to enforce. When most jobs are covered, change the org-baseline policy's Egress policy to Block so anything not yet governed is denied by default rather than allowed.
Switching a policy's egress mode in the form resets DNS policy and Sudo policy to that mode's defaults, so review all three fields after you change one.