Skip to content

Commit 822db89

Browse files
imilchevchris-rock
andauthored
📝 Describe suggested setup for public repos (#51)
* describe suggested setup for public repos Signed-off-by: Ivan Milchev <[email protected]> * fix typos Signed-off-by: Ivan Milchev <[email protected]> * fix formatting Signed-off-by: Ivan Milchev <[email protected]> --------- Signed-off-by: Ivan Milchev <[email protected]> Co-authored-by: Christoph Hartmann <[email protected]>
1 parent 2f5de24 commit 822db89

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

.github/actions/spelling/expect.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ dfd
55
gaurav
66
healthz
77
myapp
8+
mshick
89
nginx
910
notsigned
1011
prcomment

README.md

+140
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,146 @@ jobs:
133133
run: echo ${{ steps.docker_build.outputs.digest }}
134134
```
135135
136+
## Suggested setup for public repos
137+
138+
There are some caveats for public repositories that should be taken into account when setting up actions that should run for forks. Below we describe the default GitHub behaviour with examples, list the potential risks with it and then provide our suggested solution.
139+
140+
### GitHub default behaviour
141+
142+
Our GitHub actions require a secret (the Mondoo service account) to be able to run a scan. By default, workflows from forks do not have access to the secrets in the upstream repository. However, in certain cases it might be required that a secret is made accessible for forks. For example, a repository that uses our actions to run security and misconfiguration checks would probably want to do so for forks as well.
143+
144+
### The behaviour we want
145+
146+
We would like to explicitly approve every change in PR before it is being executed with access to our repository's secrets. Only after all changes are reviewed we can allow the PR to run with such an access.
147+
148+
### The solution
149+
150+
Assume we have the following workflow that runs for every PR:
151+
152+
```yaml
153+
name: K8s Manifest Scanning
154+
on:
155+
pull_request:
156+
157+
jobs:
158+
k8s-manifest-tests:
159+
runs-on: ubuntu-latest
160+
name: Test k8s manifest scanning
161+
steps:
162+
- uses: actions/checkout@v3
163+
164+
- name: Scan k8s manifest
165+
uses: ./k8s-manifest
166+
env:
167+
MONDOO_CONFIG_BASE64: ${{ secrets.MONDOO_SERVICE_ACCOUNT }}
168+
with:
169+
path: ./.github/test_files/k8s-manifest.yaml
170+
```
171+
172+
It would not work for forks because we are trying to access `${{ secrets.MONDOO_SERVICE_ACCOUNT }}`. To be able to support this use-case first, let's extract the job into a reusable workflow.
173+
174+
```yaml
175+
name: K8s Manifest Scanning
176+
on:
177+
workflow_call:
178+
secrets:
179+
MONDOO_SERVICE_ACCOUNT:
180+
required: true
181+
182+
jobs:
183+
k8s-manifest-tests:
184+
runs-on: ubuntu-latest
185+
name: Test k8s manifest scanning
186+
steps:
187+
- uses: actions/checkout@v3
188+
189+
- name: Scan k8s manifest
190+
uses: ./k8s-manifest
191+
env:
192+
MONDOO_CONFIG_BASE64: ${{ secrets.MONDOO_SERVICE_ACCOUNT }}
193+
with:
194+
path: ./.github/test_files/k8s-manifest.yaml
195+
```
196+
197+
Then we need to adjust the workflow that runs for our PRs to use the reusable workflow. We also need to make sure it runs only for non-fork PRs.
198+
199+
```yaml
200+
name: K8s Manifest Scanning
201+
on:
202+
pull_request:
203+
204+
jobs:
205+
k8s-manifest-tests:
206+
name: Test k8s manifest scanning
207+
# Make sure the workflow runs only for non-forks and non-dependabot PRs
208+
if: |
209+
!github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]'
210+
uses: ./.github/workflows/manifest-scan.yml # <- path to the reusable workflow
211+
secrets:
212+
MONDOO_SERVICE_ACCOUNT: ${{ secrets.MONDOO_SERVICE_ACCOUNT }} # <- pass the secret to the reusable workflow
213+
```
214+
215+
Then we need to define another workflow that would run only for forked PRs. We also want to make sure that it will run after an explicit approval. For that we will use the labels on the PR itself. If the `run tests` label is present, we run the tests and remove it. Otherwise, we fail the pipeline because the tests have not run and we add a comment to the PR that states that. In this way, we make sure that the tests are always executed (and not forgotten) and we also have granular control of when they are run.
216+
217+
```yaml
218+
name: K8s Manifest Scanning (forks)
219+
220+
on:
221+
pull_request_target: # <- this is an important change. Makes sure that secrets are accessible to the fork
222+
types: [opened, synchronize, reopened, labeled]
223+
224+
permissions:
225+
contents: read
226+
227+
jobs:
228+
check-label:
229+
name: Check label
230+
runs-on: ubuntu-latest
231+
# If this is not a fork do not start this step
232+
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.head.repo.fork }}
233+
permissions:
234+
pull-requests: write
235+
steps:
236+
- uses: actions/checkout@v3
237+
with:
238+
persist-credentials: false
239+
- name: Check whether tests are enabled for this PR
240+
run: |
241+
echo "IS_FORK=${{ github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.head.repo.fork }}" >> $GITHUB_ENV
242+
echo "HAS_LABEL=${{ contains(github.event.pull_request.labels.*.name, 'run tests') }}" >> $GITHUB_ENV
243+
- name: Remove 'run tests' label
244+
# If the PR is created by dependabot or is a fork and has the 'run tests' label, remove it.
245+
# This makes sure that the tests will be run now and a follow-up change would require a new approval.
246+
if: ${{ env.IS_FORK == 'true' && env.HAS_LABEL == 'true' }}
247+
run: |
248+
gh pr edit ${{ github.event.pull_request.number }} --remove-label "run tests"
249+
env:
250+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
251+
# If the tests were not enabled, then we fail the workflow. We do this instead of skipping to make sure that
252+
# the tests are eventually executed. Failed workflow would not allow the PR to be merged.
253+
- name: Fail workflow
254+
if: ${{ env.IS_FORK == 'true' && env.HAS_LABEL == 'false' }}
255+
run: |
256+
echo "Not all tests have run for this PR. Please add the `run tests` label to trigger them."
257+
exit 1
258+
# Here we add a comment to the PR that states whether the tests are running or not. This is an optional step.
259+
# We have it for clarification. It does not add new comments for every change. It will edit the existing comment instead.
260+
- name: Update PR comment
261+
uses: mshick/add-pr-comment@v2
262+
if: always()
263+
with:
264+
message: |
265+
✅ Tests will run for this PR. Once they succeed it can be merged.
266+
message-failure: |
267+
❌ Not all tests have run for this PR. Please add the `run tests` label to trigger them.
268+
tests:
269+
name: Test k8s manifest scanning
270+
needs: [check-label] # <- only run this if the check-label job was successful
271+
uses: ./.github/workflows/manifest-scan.yml # <- path to the reusable workflow
272+
secrets:
273+
MONDOO_SERVICE_ACCOUNT: ${{ secrets.MONDOO_SERVICE_ACCOUNT }} # <- pass the secret to the reusable workflow
274+
```
275+
136276
## Join the community!
137277
138278
Join the [Mondoo Community GitHub Discussions](https://github.com/orgs/mondoohq/discussions) to collaborate on policy as code and security automation.

0 commit comments

Comments
 (0)