Skip to content

Commit b2ea49f

Browse files
yanksyoonCopilotis-devops-bot
authored
chore: eject repo policy compliance (#665)
* mark external repo-policy-compliance configurations as deprecated * add allow-forked-repository charm configuration option * add deprecated configuration option warning * use type casting for bool charm configs * change config option name to allow-external-contributor * parse allow-external-contributor charm config option * test: configuration parsing unit tests * fix: add use_aproxy default value * add allow_external_contributor configuration to application config * add deprecation warning for repo-policy-compliance-client * add allow_external_contributor option to application * test: initial forked repo testing * debug * debug: ping me when test done * feat: enhance integration tests for trusted and untrusted forked repositories * feat: update GitHub client initialization to use Token authentication * chore: revert charm integration tests * chore: revert charm integration tests * chore: merge pre_job_contents_dict generation * feat: add GitHub and OpenStack configuration options for integration tests * refactor: simplify configuration file reading in RunningApplication class * chore: remove deprecated OpenStack ARM64 options from pytest configuration * feat: add integration tests configuration to GitHub Actions and tox * chore: lint fixes * refactor: streamline OpenStack options and remove deprecated token_alt fixture * chore: update integration test environment variables for OpenStack * chore: undo charm CI testing changes * chore: refactor testing args parsing to upper level * refactor: remove environment variable dependency for alternate GitHub token in tests * chore: apply pflake8 rules to all tests * chore: remove reference to unused env var * test: adapt tests to latest GH repository secrets * chore: remove integration test requirements.txt * chore: tidy integration test & fail if required params not supplied * test: update docstring * ci: install application package before testing * ci: test * ci: fix secrets mapping * ci: skip heavy testing for debug * ci: debug * fix: proxy configuration check * test: use proxies * test: use proxies in fixtures * test: use test configured flavor/image * test: application accept 204 * test: use configurable metrics log path * test: prefer reactive configuration by default for tests * test: prefer non reactive configuration by default to save deploy components * test: remove duplicate health checks (create app health check enabled) * test: fix create PR from fork * test: fix PR base * test: stepped PR deployment * refactor: remove unused dispatch workflow function and update tests to use get_pr_workflow_runs * ci: trigger * fix: PR base * test: origina/upstream/fork repository differentiation * ci: trigger * test: fix use aproxy configuration by default * test: get all logs from a run * test: log cli output * test: fix log assertion * ci: remove debug * ci: renable charm tests * fix: lint fixes * docs: update allow-external-contributor configuration name * ci: revert debug test * test: revert subdir tests per-file-ignores settings * test: fix syntax err * test: add openstack user/project domain name * test: add openstack user/project domain name * test: add openstack user/project domain name * test: add openstack cleanup fixture * test: remove runtime hook * feat: flush runners on external contributor config change * feat: add allow_external_contributor to stored state * chore: increment app version & docs: update changelog * fix: use stored state * fix: only check user association for pull_request events * chore: whitespace for concatenated string * revert removed whitespace from test fixture docstring * feat: check all events that can be triggered by external contributors * chore: eject repo-policy-compliance * test: eject repo policy configs * docs: replace repo-policy docs w/ allow-external-contributor * chore: introduce external-contributor-check-failure to metrics * chore: deprecation related changes * docs: improve docs & remove extra statements * feat: issue metrics on allow_external_contributor check failure * chore: clean up comments * test: lint fixes * ci: remove removed test * doc: fix doc links * doc: fix vale suggestions * fix: link * docs: improve docs * docs: revert all lxd doc changes * chore: remove unused repo-policy url config * docs: make vale happy * docs: make vale happy #2 * Initial plan * docs: reorganize documentation structure per review feedback Co-authored-by: yanksyoon <37652070+yanksyoon@users.noreply.github.com> * docs: update how-to index with new guide references Co-authored-by: yanksyoon <37652070+yanksyoon@users.noreply.github.com> * Initial plan * fix: capture timestamp at failure time for external-contributor-check metrics Co-authored-by: yanksyoon <37652070+yanksyoon@users.noreply.github.com> * fix: copilot feedback --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Platform Engineering Bot <135168451+is-devops-bot@users.noreply.github.com>
1 parent 71b2fcc commit b2ea49f

37 files changed

Lines changed: 197 additions & 750 deletions

.github/workflows/integration_test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
juju-channel: 3.6/stable
2121
provider: lxd
2222
test-tox-env: integration-juju3.6
23-
modules: '["test_multi_unit_same_machine", "test_charm_metrics_failure", "test_charm_metrics_success", "test_charm_fork_repo", "test_charm_fork_path_change", "test_charm_no_runner", "test_charm_runner", "test_charm_upgrade", "test_reactive"]'
23+
modules: '["test_multi_unit_same_machine", "test_charm_metrics_failure", "test_charm_metrics_success", "test_charm_fork_path_change", "test_charm_no_runner", "test_charm_runner", "test_charm_upgrade", "test_reactive"]'
2424
# INTEGRATION_TOKEN, INTEGRATION_TOKEN_ALT, OS_* are passed through INTEGRATION_TEST_SECRET_ENV_VALUE_<N>
2525
# mapping. See CONTRIBUTING.md for more details.
2626
extra-arguments: |
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
aproxy
22
Aproxy
33
iptables
4-
Tmate
4+
Tmate
5+
untrusted

config.yaml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,6 @@ options:
8585
Minutes between each reconciliation of the current runners state and their targeted state.
8686
On reconciliation, the charm polls the state of runners and see if actions are needed. The
8787
value should be kept low, unless Github API rate limiting is encountered.
88-
repo-policy-compliance-token:
89-
type: string
90-
description: >-
91-
DEPRECATED, please use allow-external-contributor configuration option instead.
92-
The token to authenticate with the repository-policy-compliance service in order to
93-
generate one-time-tokens. This option requires the repo-policy-compliance-url to be set.
94-
If not set, the repository-policy-compliance service will not be used.
95-
repo-policy-compliance-url:
96-
type: string
97-
description: >-
98-
DEPRECATED, please use allow-external-contributor configuration option instead
99-
The URL to the repository-policy-compliance service. This option requires the
100-
repo-policy-compliance-token to be set. If not set, the repository-policy-compliance service
101-
will not be used. This option is only supported when using OpenStack Cloud.
10288
allow-external-contributor:
10389
type: boolean
10490
default: True

docs/changelog.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
This changelog documents user-relevant changes to the GitHub runner charm.
44

5+
## 2026-02-02
6+
7+
- Deprecated `repo-policy-compliance` service.
8+
59
## 2025-01-26
610

711
- Add machine input parameter for terraform charm module to allow targeting specific machines for
@@ -43,7 +47,7 @@ GitHub runner image builder side.
4347

4448
## 2025-12-01
4549

46-
- Added timeouts to API calls (Openstack,GitHub,Repo policy compliance) to fix a hanging GitHub runner manager application.
50+
- Added timeouts to API calls (OpenStack, GitHub, repo-policy-compliance) to fix a hanging GitHub runner manager application.
4751

4852
## 2025-11-30
4953

@@ -74,7 +78,6 @@ GitHub runner image builder side.
7478

7579
- Fix issue with scaling down overshooting in deleting runners after cleanup
7680

77-
7881
## 2025-08-20
7982

8083
- Document relevant log files.
@@ -107,7 +110,7 @@ GitHub runner image builder side.
107110
## 2025-07-09
108111

109112
- Specify max supported nova compute API to be 2.91. This fixes an issue where the charm could fail
110-
due to a bug on the OpenStack side: https://bugs.launchpad.net/nova/+bug/2095364
113+
due to a bug on the OpenStack side: https://bugs.launchpad.net/nova/+bug/2095364
111114

112115
### 2025-06-30
113116

@@ -127,8 +130,7 @@ GitHub runner image builder side.
127130
### 2025-06-16
128131

129132
- Revert `copytruncate logrotate` method for reactive processes, as `copytruncate` keeps log files on disks and does not remove them, and each process is writing to a new file leading to a huge and increasing amount
130-
of zero sized files in the reactive log directory. This is a temporary fix until a better solution is implemented, as it has the downside that long lived reactive processes may write to deleted log files.
131-
133+
of zero sized files in the reactive log directory. This is a temporary fix until a better solution is implemented, as it has the downside that long lived reactive processes may write to deleted log files.
132134

133135
### 2025-06-12
134136

@@ -140,9 +142,9 @@ of zero sized files in the reactive log directory. This is a temporary fix until
140142

141143
### 2025-06-04
142144

143-
- Reduce the reconcile-interval configuration from 10 minutes to 5 minutes. This is the interval
144-
between reconciling the current and intended number of runners. The value should be kept low,
145-
unless GitHub API rate limiting is encountered.
145+
- Reduce the reconcile-interval configuration from 10 minutes to 5 minutes. This is the interval
146+
between reconciling the current and intended number of runners. The value should be kept low,
147+
unless GitHub API rate limiting is encountered.
146148
- Removed the reconcile-runners Juju action.
147149

148150
### 2025-06-03
@@ -151,9 +153,8 @@ unless GitHub API rate limiting is encountered.
151153

152154
### 2025-05-22
153155

154-
- Add possibility to run a script in the pre-job phase of a runner. This can be useful to setup
155-
network/infrastructure specific things.
156-
156+
- Add possibility to run a script in the pre-job phase of a runner. This can be useful to setup
157+
network/infrastructure specific things.
157158

158159
### 2025-05-09
159160

@@ -162,8 +163,8 @@ network/infrastructure specific things.
162163
### 2025-05-06
163164

164165
- The ssh health checks are removed and GitHub is used instead to get the runners health
165-
information. This implies many changes in both the structure of the project and its functionality. Potentially, many race conditions should
166-
disappear.
166+
information. This implies many changes in both the structure of the project and its functionality. Potentially, many race conditions should
167+
disappear.
167168

168169
### 2025-04-28
169170

@@ -197,7 +198,7 @@ disappear.
197198
### 2025-03-24
198199

199200
- New terraform product module. This module is composed of one github-runner-image-builder application and the related
200-
github-runner applications.
201+
github-runner applications.
201202

202203
### 2024-12-13
203204

@@ -243,14 +244,14 @@ github-runner applications.
243244
### 2024-10-17
244245

245246
- Use in-memory authentication instead of clouds.yaml on disk for OpenStack. This prevents
246-
the multi-processing fighting over the file handle for the clouds.yaml file in the `github-runner-manager`.
247+
the multi-processing fighting over the file handle for the clouds.yaml file in the `github-runner-manager`.
247248

248249
- Fixed a bug where metrics storage for unmatched runners could not get cleaned up.
249250

250251
### 2024-10-11
251252

252253
- Added support for COS integration with reactive runners.
253-
- The charm now creates a dedicated user which is used for running the reactive process and
254+
- The charm now creates a dedicated user which is used for running the reactive process and
254255
storing metrics and ssh keys (also for non-reactive mode).
255256

256257
### 2024-10-07

docs/explanation/security.md

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,46 @@ This document describes the security design of the GitHub runner charm. The char
44

55
## Remote code execution risk
66

7-
The charm manages GitHub self-hosted runners to run GitHub Actions jobs. This allows users on GitHub to execute code on the servers hosting the runners, which poses a remote code execution risk if the code is not trusted. Therefore, the charm should only spawn runners to trusted organizations or repositories.
7+
The charm manages GitHub self-hosted runners to run GitHub Actions jobs. This allows users on GitHub to execute code on the servers hosting the runners, which poses a remote code execution risk if the code has not been reviewed or authorized. Therefore, the charm should only spawn runners to trusted organizations or repositories.
88

9-
For third-party contributions, the charm can integrate with the [Repo Policy Compliance charm](https://charmhub.io/repo-policy-compliance) to manage the repository policy. With this integration, the self-hosted runner will not execute the GitHub jobs if the policy is not met. See [working with outside collaborators](https://charmhub.io/github-runner/docs/how-to-comply-security#working-with-outside-collaborators) for the recommended settings to ensure the code is reviewed by a trusted user prior to execution in the runner.
9+
For external contributor security, see [How to manage external contributors securely](../how-to/manage-external-contributors.md) for configuration options and recommended practices.
1010

1111
### Good practices
1212

1313
- Only register the GitHub self-hosted runners to a trusted organization or repository so that only workflows from trusted users are able to run on the runners.
14-
- For outside collaborators: Use the [`repo-policy-compliance` charm](https://charmhub.io/repo-policy-compliance) with [policy for outside collaborators](https://charmhub.io/github-runner/docs/how-to-comply-security#working-with-outside-collaborators) to ensure the code executed in runners are reviewed by a trusted user.
14+
- For outside collaborators: Use the `allow-external-contributor` configuration option (set to `false`) to restrict workflow execution to users with COLLABORATOR, MEMBER, or OWNER status. This prevents unauthorized code execution from external contributors.
15+
- Configure appropriate repository settings and protection rules to ensure the code executed in runners are reviewed by a trusted user.
16+
17+
### Recommended security practices
18+
19+
When working with external contributors, consider the following security practices:
20+
21+
#### Repository configuration
22+
23+
- For outside collaborators, set permissions to read-only. See [here](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/managing-teams-and-people-with-access-to-your-repository#changing-permissions-for-a-team-or-person) for instructions to change collaborator permissions.
24+
25+
#### Branch protection rules
26+
27+
Create the following branch protection rules using the instructions [here](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule#creating-a-branch-protection-rule):
28+
29+
- Branch name pattern `**` with `Require signed commits` enabled.
30+
- Branch name pattern matching only the default branch of the repository, such as `main`, with the following enabled:
31+
- `Dismiss stale pull request approvals when new commits are pushed`
32+
- `Required signed commits`
33+
- `Do not allow bypassing the above settings`
34+
35+
#### Working with external contributors
36+
37+
When `allow-external-contributor` is set to `false`, external contributors can still contribute through the following workflow:
38+
39+
1. External contributors create pull requests as usual
40+
2. A repository maintainer with COLLABORATOR, MEMBER, or OWNER status reviews the code
41+
3. If the code is safe, the maintainer can:
42+
43+
- Approve and merge the pull request to another branch (workflows will run with maintainer permissions)
44+
- Manually trigger workflow runs if needed (using workflow dispatch on the target branch)
45+
46+
This approach ensures that all code from external contributors is reviewed by trusted users before execution on self-hosted runners.
1547

1648
## Permission for GitHub app or personal access token
1749

docs/how-to/comply-security.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,29 @@
22

33
According to GitHub, running code inside the GitHub self-hosted runner [poses a significant security risk of arbitrary code execution](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#self-hosted-runner-security). The self-hosted runners managed by the charm are isolated in its own single-use virtual machine instance. In addition, the charm enforces some repository settings to ensure all code running on the self-hosted runners is reviewed by someone trusted.
44

5-
The charm can be integrated with the [Repo Policy Compliance charm](https://charmhub.io/repo-policy-compliance) to enforce a set of good practices around GitHub repository settings. Self-hosted runners managed by the charm will not run jobs on repositories unless they are compliant with the practices.
5+
The charm provides the `allow-external-contributor` configuration option to control whether workflows triggered by external contributors can execute on the self-hosted runners. When set to `false`, only users with COLLABORATOR, MEMBER, or OWNER status can trigger workflows from pull requests, reviews, and comments.
66

7-
In this guide, a recommended set of policies will be presented.
7+
In this guide, a recommended set of policies and security practices will be presented.
8+
9+
## External contributor access control
10+
11+
Configure the charm to restrict external contributor access:
12+
13+
```bash
14+
juju config github-runner allow-external-contributor=false
15+
```
16+
17+
With this setting, workflows will only run for users with the following GitHub author associations:
18+
- OWNER - Repository or organization owners
19+
- MEMBER - Organization members
20+
- COLLABORATOR - Users with explicit collaborator access
21+
22+
The charm checks author associations for these events:
23+
- `pull_request` - Pull requests from external contributors
24+
- `pull_request_target` - Pull request targeting (designed for handling PRs from forks)
25+
- `pull_request_review` - Pull request reviews from external contributors
26+
- `pull_request_review_comment` - Comments on pull request diffs from external contributors
27+
- `issue_comment` - Comments on issues or pull requests from external contributors
828

929
## Recommended policy
1030

@@ -20,4 +40,12 @@ With these settings, the common workflow of creating branches with pull requests
2040

2141
### Working with outside collaborators
2242

23-
Generally, outside collaborators are not completely trusted, but still would need to contribute in some manner. As such, this charm requires pull requests by outside collaborators to be reviewed by someone with `write` permission or above. Once the review is completed, the reviewer should add a comment including the following string: `/canonical/self-hosted-runners/run-workflows <commit SHA>`, where `<commit SHA>` is the commit SHA of the approved commit. Once posted, the self-hosted runners will run the workflow for this commit.
43+
When `allow-external-contributor` is set to `false`, outside collaborators can still contribute through the following secure workflow:
44+
45+
1. External contributors create pull requests as usual
46+
2. A repository maintainer with COLLABORATOR, MEMBER, or OWNER status reviews the code
47+
3. If the code is safe, the maintainer can:
48+
- Approve and merge the pull request to another branch (workflows will run with the permissions of the maintainer)
49+
- Manually trigger workflow runs if needed (using workflow dispatch on the target branch)
50+
51+
This approach ensures that all code from external contributors is reviewed by trusted users before execution on self-hosted runners, eliminating the need for manual comment-based approval workflows.

docs/how-to/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ and using the Github Runner charm.
1616

1717
## Security
1818
* [Comply with security requirements]
19+
* [Manage external contributors securely]
20+
* [Troubleshoot]
1921

2022
## Development
2123
* [Contribute]
@@ -30,4 +32,6 @@ and using the Github Runner charm.
3032
[Spawn OpenStack runner]: openstack-runner.md
3133
[Set up reactive spawning]: reactive.md
3234
[Comply with security requirements]: comply-security.md
35+
[Manage external contributors securely]: manage-external-contributors.md
36+
[Troubleshoot]: troubleshoot.md
3337
[Contribute]: contribute.md
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# How to manage external contributors securely
2+
3+
According to GitHub, running code inside the GitHub self-hosted runner [poses a significant security risk of arbitrary code execution](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#self-hosted-runner-security). The self-hosted runners managed by the charm are isolated in their own single-use virtual machine instances. In addition, the charm provides security controls to ensure that code from external contributors is only executed when authorized.
4+
5+
The charm provides the `allow-external-contributor` configuration option to control whether workflows triggered by external contributors can execute on the self-hosted runners. When set to `false`, only users with COLLABORATOR, MEMBER, or OWNER status can trigger workflows.
6+
7+
In this guide, we'll explain how to configure external contributor access.
8+
9+
## External contributor access control
10+
11+
An external contributor is anyone whose GitHub author association is not OWNER, MEMBER, or COLLABORATOR. For internal pull requests (where the head and base repositories are the same), the association check is not applied; those runs are treated as internal.
12+
13+
The charm checks the GitHub author association for the following events that can be triggered by external contributors:
14+
15+
- `pull_request` - Pull requests from external contributors
16+
- `pull_request_target` - Pull request targeting (designed for handling PRs from forks)
17+
- `pull_request_review` - Pull request reviews from external contributors
18+
- `pull_request_review_comment` - Comments on pull request diffs from external contributors
19+
- `issue_comment` - Comments on issues or pull requests from external contributors
20+
21+
### Disable external contributor access
22+
23+
Prevent external contributors from triggering workflows. Run:
24+
25+
```bash
26+
juju config github-runner allow-external-contributor=false
27+
```
28+
29+
With this setting, only users with the following GitHub author associations can trigger workflows:
30+
31+
- OWNER - Repository or organization owners
32+
- MEMBER - Organization members
33+
- COLLABORATOR - Users with explicit collaborator access
34+
35+
### Enable external contributor access
36+
37+
Allow all external contributors to trigger workflows. Run:
38+
39+
```bash
40+
juju config github-runner allow-external-contributor=true
41+
```
42+
43+
**Warning**: This setting allows any external contributor to trigger workflow execution on your self-hosted runners. Only use this in trusted environments or when you have other security controls in place.

docs/how-to/troubleshoot.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# How to troubleshoot
2+
3+
This guide covers troubleshooting for common issues that users may encounter when working with the GitHub runner charm.
4+
5+
## External contributor workflows
6+
7+
### Workflows not running for external contributors
8+
9+
If workflows are not running for external contributors when `allow-external-contributor=false`:
10+
11+
1. Check the runner logs for authorization errors
12+
2. Verify the user's author association in the GitHub repository
13+
14+
### Workflows running for unexpected users
15+
16+
If you notice workflows running for users who shouldn't have access:
17+
18+
1. Set `allow-external-contributor=false`
19+
2. Review repository collaborator permissions
20+
3. Check for any bypass rules in branch protection settings
21+
4. Audit recent workflow runs in the GitHub Actions tab

docs/index.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ Thinking about using the GitHub runner charm for your next project? [Get in touc
8585
1. [Debug with SSH](local-lxd/how-to/debug-with-ssh.md)
8686
1. [Deploy on ARM64](local-lxd/how-to/deploy-on-arm64.md)
8787
1. [Integrate with COS](local-lxd/how-to/integrate-with-cos.md)
88-
1. [Comply with repository policies](local-lxd/how-to/repo-policy.md)
8988
1. [Run on LXD cloud](local-lxd/how-to/run-on-lxd.md)
9089
1. [Set base image](local-lxd/how-to/set-base-image.md)
9190
1. [Reference](local-lxd/reference)

0 commit comments

Comments
 (0)