Skip to content
This repository was archived by the owner on Nov 30, 2022. It is now read-only.

trigger workflows to run for pull_request event#86

Merged
NevilleS merged 11 commits into
mainfrom
seanpreston-26-enable-ci
Nov 19, 2021
Merged

trigger workflows to run for pull_request event#86
NevilleS merged 11 commits into
mainfrom
seanpreston-26-enable-ci

Conversation

@seanpreston
Copy link
Copy Markdown
Contributor

@seanpreston seanpreston commented Nov 18, 2021

Purpose

This PR adds the pull_request_target event to our workflows, which should allow PRs on forked repos to trigger workflow events (ie. CI via Github Actions).

See: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#pull_request_target for full docs.

This event runs in the base context of a pull request, so I believe this change has to be made in the repo itself, before any workflows on forked PRs will run.

As @iamkelllly has mentioned here: #26 (comment), there's also something we'll need to do with the Github tokens, to stop them from being able to read secrets being stored in the underlying repository, so in lieu of completing that here I've changed the repository settings to force us to approve any workflow runs for outside collaborators, which we can choose to not do until we're sure the token issue is handled.

Screenshot 2021-11-18 at 11 28 21

This should yield an approval process like: https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks

Ticket

Closes #26

@seanpreston seanpreston changed the title trigger workflows to run for pull_request_target event trigger workflows to run for pull_request_target event Nov 18, 2021
@NevilleS
Copy link
Copy Markdown
Contributor

I'd love a few others to weigh in here on the security side (paging @ThomasLaPiana and @PSalant726) just so we get this right. I like the idea of allowing forked PRs to run our actions for CI, but want to ensure we are very careful about how that can expose the GitHub secrets.

A couple articles I found on this:

On my reading I think I'd prefer:

  • using pull_request (instead of pull_request_target) as the trigger, which should be able to build & run unit tests without any secrets... I think?
  • only ever using the docker secrets on main, never on any pull_request or pull_request_target workflows
  • having a separate workflow for the integration tests. this can be manual for now (i.e. a core member checks out and runs the code), but we could also make it so you add a label like safe-to-test and that allows integration tests to run- see the example from here https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
    on:
      pull_request_target:
        types: [labeled]

    jobs:
      build:
        name: Build and test
        runs-on: ubuntu-latest
        if: contains(github.event.pull_request.labels.*.name, 'safe to test')

Comment thread .github/workflows/pr_checks.yml Outdated
on: [push]
on: [
push,
pull_request_target
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR from my comment (#86 (comment))

If you set this to pull_request instead of pull_request_target for now, we'll get 90% of the value of CI but I'd expect tests that rely on secrets to fail. That's a secure place to start from

Copy link
Copy Markdown
Contributor

@PSalant726 PSalant726 Nov 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building on this, I don't think it achieves what we want anyway. From the documentation linked by Sean:

This event runs in the context of the base of the pull request, rather than in the merge commit as the pull_request event does.

I could be misunderstanding, but I interpret this as "run our workflows against the commit from which the PR was branched", not the latest commit on the PR itself. It's intended to be used as more of a housekeeping trigger, to add labels etc. to PRs. Isn't the intent to run CI actions against the changeset on the PR?

Separately, these changes, as written, don't seem to be using any of the additional permissions afforded by the pull_request_target trigger except to allow for execution of the external resource integration tests. Effectively, this change only serves to expose the ${{ secrets.REDSHIFT_TEST_URI }} and ${{ secrets.SNOWFLAKE_TEST_URI }} values to PRs opened by potentially untrusted users (repo forks).

@seanpreston
Copy link
Copy Markdown
Contributor Author

If you set this to pull_request instead of pull_request_target for now, we'll get 90% of the value of CI but I'd expect tests that rely on secrets to fail. That's a secure place to start from

Will update.

having a separate workflow for the integration tests. this can be manual for now (i.e. a core member checks out and runs the code), but we could also make it so you add a label like safe-to-test and that allows integration tests to run- see the example from here https://securitylab.github.com/research/github-actions-preventing-pwn-requests/

I'd like to understand more about how the tokens are issued too. If it's the case that the tokens are short lived and can be set to only be generated on manual approval of a job run, it might not be a huge issue either way.

Copy link
Copy Markdown
Contributor

@PSalant726 PSalant726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NevilleS 's suggestion about configuring the external integration tests to only run against PR's labeled safe-to-test (or similar) seems like a good potential route forward.

As another option, we could create an additional, similar automation that restricts the execution of the external integration tests only to PRs opened either 1) from a branch off of the repo itself (not a fork) or 2) by a member of the Ethyca GH org and/or the @ethycadev user group.

I don't see any way for us to safely automate the execution of any job that requires access to repository secrets when the PR being tested was opened by an untrusted user. For PRs opened by external contributors, I would recommend that an Ethyca employee first reviews the code changes here on GH, then, if everything seems safe, checkout the fork's branch locally and execute the external integration tests manually. Since all PRs require an approval from a maintainer before merging anyway, this extra step doesn't seem like that much to ask.

As a last step, we should find a way to mark the external integration tests as "not run", and prevent the pipeline from displaying as passed, so we don't miss the previous manual step.

Comment thread .github/workflows/pr_checks.yml Outdated
on: [push]
on: [
push,
pull_request_target
Copy link
Copy Markdown
Contributor

@PSalant726 PSalant726 Nov 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building on this, I don't think it achieves what we want anyway. From the documentation linked by Sean:

This event runs in the context of the base of the pull request, rather than in the merge commit as the pull_request event does.

I could be misunderstanding, but I interpret this as "run our workflows against the commit from which the PR was branched", not the latest commit on the PR itself. It's intended to be used as more of a housekeeping trigger, to add labels etc. to PRs. Isn't the intent to run CI actions against the changeset on the PR?

Separately, these changes, as written, don't seem to be using any of the additional permissions afforded by the pull_request_target trigger except to allow for execution of the external resource integration tests. Effectively, this change only serves to expose the ${{ secrets.REDSHIFT_TEST_URI }} and ${{ secrets.SNOWFLAKE_TEST_URI }} values to PRs opened by potentially untrusted users (repo forks).

@NevilleS
Copy link
Copy Markdown
Contributor

NevilleS commented Nov 18, 2021 via email

@seanpreston
Copy link
Copy Markdown
Contributor Author

To be thorough I have done some testing this afternoon by opening up a PR against this repo from a new account. I can confirm that the new account is unable to add labels:

Screenshot 2021-11-18 at 18 03 57

@iamkelllly
Copy link
Copy Markdown
Contributor

Given that we're referencing pull_request rather than pull_request_target then, can we update the PR title @seanpreston ?

@seanpreston seanpreston changed the title trigger workflows to run for pull_request_target event trigger workflows to run for pull_request event Nov 19, 2021
@seanpreston
Copy link
Copy Markdown
Contributor Author

seanpreston commented Nov 19, 2021

As a last step, we should find a way to mark the external integration tests as "not run", and prevent the pipeline from displaying as passed, so we don't miss the previous manual step.

@PSalant726, it looks like this happens automatically:

Screenshot 2021-11-19 at 12 17 55

UPDATE: and then once the label has been added:
Screenshot 2021-11-19 at 12 52 05

We ought to stop every step from re-running each time a PR is labeled if we're also going to run them on push

@seanpreston seanpreston added run unsafe ci checks Triggers running of unsafe CI checks and removed safe to test labels Nov 19, 2021
@seanpreston seanpreston removed the run unsafe ci checks Triggers running of unsafe CI checks label Nov 19, 2021
@seanpreston seanpreston added the run unsafe ci checks Triggers running of unsafe CI checks label Nov 19, 2021
@seanpreston
Copy link
Copy Markdown
Contributor Author

I've updated this PR to factor in a couple of changes requested by both @NevilleS and @PSalant726:

  • CI checks are now split into Safe and Unsafe categories
  • Safe CI checks are run on every pull_request event. This allows forked PRs to run them (?), and is also triggered every time a commit is added to the PR (as before).
  • Unsafe CI checks are triggered by the labeled type of pull_request events, and will only run if the label added contains the text run unsafe ci checks. NB. this category will still show a skipped label in the list of checks for push events, so the reviewer is aware that these checks have not run at the time of review.

@seanpreston seanpreston added run unsafe ci checks Triggers running of unsafe CI checks and removed run unsafe ci checks Triggers running of unsafe CI checks labels Nov 19, 2021
jobs:
Integration-Tests-External:
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'run unsafe ci checks')
Copy link
Copy Markdown
Contributor Author

@seanpreston seanpreston Nov 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition was a bit confusing to me on first pass, so to break down for anyone else:

github.event.pull_request.labels.*.name this statement is applying a filter on the github.event.pull_request.labels var, pull out a list of label names, e.g. ["safe to run", "dont merge", ...].

contains(list, "value") is then check if "value" is an element of list.

It seems simple when you put it that way, but if you don't know about the filter stage, it could look as though github.event.pull_request.labels.*.name evaluates to a string and we're checking if that string contains the PR name (which would be less robust).

https://docs.github.com/en/actions/learn-github-actions/expressions#object-filters

Copy link
Copy Markdown
Contributor

@NevilleS NevilleS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me now.

However, with the number of actions we're running, I think we need to combine some of these jobs together to make the whole thing run faster because we're definitely burning a ton of CI minutes on every single PR

I'll open a new issue for that

Comment thread src/fidesops/main.py Outdated
@seanpreston
Copy link
Copy Markdown
Contributor Author

seanpreston commented Nov 19, 2021

However, with the number of actions we're running, I think we need to combine some of these jobs together to make the whole thing run faster because we're definitely burning a ton of CI minutes on every single PR

The number of minutes burned might actually go down with this change, since we're switching from running the workflows on every push to only events related to pull requests.

Copy link
Copy Markdown
Contributor

@PSalant726 PSalant726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NevilleS -

However, with the number of actions we're running, I think we need to combine some of these jobs together to make the whole thing run faster because we're definitely burning a ton of CI minutes on every single PR

Ideally the pipeline would:

  • Build the container artifacts in a build stage, and make them available to the other stages that require them
  • Execute static analysis tools and test harnesses in discreet pipeline lint and test stages, dependent on the build artifacts where needed (and, crucially, not dependent where not needed)

We have an issue in fidesctl to make a similar change.

@seanpreston -
It's not enough to block this PR for me, but I think a cleaner implementation would keep things in a single file with a generic name like Fidesops. The jobs are still discreet and can have if conditions applied independently.

@NevilleS NevilleS merged commit 5c2caf1 into main Nov 19, 2021
@NevilleS NevilleS deleted the seanpreston-26-enable-ci branch November 19, 2021 16:38
@seanpreston
Copy link
Copy Markdown
Contributor Author

It's not enough to block this PR for me, but I think a cleaner implementation would keep things in a single file with a generic name like Fidesops. The jobs are still discreet and can have if conditions applied independently.

I did have it like this initially. Because we're using both push and pull_request triggers, we'd end up needing custom if: ... conditionals on every job to be sure we're not running every job in both contexts. That was generating 15 job runs for every push which seemed excessive. There might be another way to configure it that I didn't discover, but this felt clean enough, and has the added benefit of anything unsafe being explicit and in its own file.

sanders41 pushed a commit that referenced this pull request Sep 22, 2022
* trigger workflows to run for pull_request_target event

* change to only pull_request

* check safe to test label

* what happens when a PR with the safe-to-test label is pushed to

* split pr_checks into safe + unsafe

* update names of jobs

* try removing push trigger

* add push trigger back so we can see the check as skipped, change label name to better reflect the action

* add pull_request back to safe checks

* remove push because pull_request synchronize should cover it

* remove arbitrary change
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

DON'T MERGE run unsafe ci checks Triggers running of unsafe CI checks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable CI for forked pull requests

5 participants