Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automation solution for GitHub processes that need a PAT #420

Open
evankanderson opened this issue Dec 6, 2024 · 16 comments
Open

Automation solution for GitHub processes that need a PAT #420

evankanderson opened this issue Dec 6, 2024 · 16 comments

Comments

@evankanderson
Copy link
Contributor

The https://github.com/mindersec/winget-pkgs repo is used to release the Minder binary to the Windows ecosystem. This process involves opening a PR against https://github.com/microsoft/winget-pkgs, which is not currently feasible for a GitHub app which is not installed on the microsoft org. The recommended solution is to use a scoped Personal Access Token (PAT).

Is there common infrastructure within OpenSSF for managing these sorts of credentials? Ideal solution would be to have an automation account ("bot"), with credentials stored in a shared-secrets solution like 1Password, and access to the secret shared amongst maintainers and OpenSSF staff.

@evankanderson
Copy link
Contributor Author

See discussion in the #wg-security-tooling channel.

@adityasaky
Copy link
Contributor

Just want to note that we've had this come up for https://github.com/gittuf/gittuf as well for packaging on winget. A generalized OpenSSF-wide solution would be fantastic.

cc @patzielinski

@steiza
Copy link
Member

steiza commented Dec 6, 2024

I just learned about winget today, so I don't totally understand what the PAT is for and how it's used here. Is the idea that you'd have a GitHub Action workflow run when a release is created (or some other trigger) in https://github.com/mindersec/winget-pkgs, in order to create a pull request between it and https://github.com/microsoft/winget-pkgs?

The reason why I want to know if it's in a GitHub Actions workflow or not is to determine if the secret can be stored as a secret in Actions, or if we need some other shared credential manager.

To unblock folks, we could have an OpenSSF staffer create a PAT that's scoped in terms of repository, permissions, and time, which should limit the amount of potential abuse. It would be a little weird for all the OpenSSF winget pull requests to be coming from @riaankleinhans though, so maybe it makes sense to create an @openssf-winget-release-bot or similar.

@evankanderson
Copy link
Contributor Author

Our release is using GitHub Actions.

We are currently using an individual's PAT stored as a GitHub Actions secret, but that feels icky, so we'd like to have a less-icky solution.

@evankanderson
Copy link
Contributor Author

@steiza
Copy link
Member

steiza commented Dec 9, 2024

Okay, so just talking through some options:

  • An OpenSSF staffer / project maintainer periodically generates PATs valid for months and they get saved in the relevant repos as Actions secrets

    • Pros: this is the status quo today, low tech, but also fairly low operational burden
    • Cons: the publishes look like they come from whoever generated the PAT; long-lived PAT can be exfiltrated and abused; if a staffer / maintainer leaves you need to rotate the PAT sooner than later
  • An OpenSSF bot account periodically generates PATs and they get saved as an Actions secret

    • Pros: don't have to rotate just because a staff member / maintainer leaves
    • Cons: you haven't really addressed the exfiltration problem; even if the PAT is stored in a cloud provider KMS that you access via an OIDC token, the PAT is still long-lived
  • Use something like octo-sts to generate short-lived PATs at time of use

    • Pros: easier for ongoing operations / doesn't require periodically regenerating long-lives PATs, lessens exfiltration risk. PAT identity would correspond to user who is doing the release.
    • Cons: more setup for projects and organizations initially (not too bad though), we're trusting Chainguard's operation of the service (we could ask them for operational details), the installed app would have somewhat broad permissions in the org

When brainstorming, I like to include an option that's a bit out there. Even if we don't choose it, having it there can help stretch the solution space. Here is that option:

  • The OpenSSF could write their own GitHub App specifically for this purpose. Similar to octo-sts, it would take in an OIDC token, and it would return a PAT for public repository pull requests
    • Pros: the OpenSSF app would have more scoped permissions than octo-sts, because it would only be for pull requests
    • Cons: More work! We'd have to write and maintain this app.

@wlynch
Copy link

wlynch commented Dec 9, 2024

we're trusting Chainguard's operation of the service (we could ask them for operational details)

Happy to be a point of contact for any questions if it would be useful!

the installed app would have somewhat broad permissions in the org

This is a side-effect of how github does app permissions. 😢
The app needs to request the superset of all possible permissions any org might want to use, and there's no option to scope these per-installation. We would love to allow users to scope these down further at the installation level if we could.

The OpenSSF could write their own GitHub App specifically for this purpose.

The iac folder has the configuration we use for our GCP deployment if that's helpful!


The bigger con of the App based approach is tokens are minted per installation (i.e. per org) - I don't believe this allows you to open PRs in other orgs that haven't installed the app.

@evankanderson
Copy link
Contributor Author

Sorry I wasn't clear -- octo-sts itself only works with GitHub App tokens, which don't work for this purpose. We'd need to have a different service for minting PATs, or work with Chainguard to extend octo-sts for that purpose. (IIRC, GitHub App tokens also can't be used against ghcr.io, so that would be two use cases for PATs.)

In any case, I'd expect openssf to run their own token-issuing service rather than relying on one run by a member company.

Another possible problem is that I'm not sure that GitHub provides APIs for managing PATs -- I think access may be web-ui-only on purpose.

@steiza
Copy link
Member

steiza commented Dec 9, 2024

Another possible problem is that I'm not sure that GitHub provides APIs for managing PATs

Oops! I missed this from my earlier investigation. It doesn't sound like we can get away from needing a long(ish) lived PAT. We could at least have that PAT stored in a separate application, that workflows make authenticated API requests to, so the app (not a GitHub OAuth App, just a regular web app) could use the PAT for that organization and open up pull requests for the requester.

Pro: individual workflows would not have direct access to the PAT to create the pull request, greatly reducing exfiltration risk
Cons: someone would have to write and maintain this app, PATs would still need to be reprovisioned every X months

@rdimitrov
Copy link

It's a random idea, but would it work if the octo-sts app is installed not only on the org but on a GitHub account(user, or a bot account in our case)? If so I wonder if we can then mint user access tokens for that account via the octo-sts app and use these tokens to open PRs on behalf of that user.

@evankanderson
Copy link
Contributor Author

I think the overall conclusion from the Dec 10 OpenSSF TAC meeting is that @SecurityCRob and @riaankleinhans would look into https://github.com/1Password/for-open-source and establishing a 1Password Teams account for the OpenSSF. Presumably, once the base 1Password infrastructure is established, they will determine a way to grant specific projects access to a "folder" within the account for things like shared keys and passwords.

I'm not sure if we made a determination as to whether each project that needs to e.g. publish to WinGet would create their own "bot" account, but that seems likely to be the best approach from a reduction-of-blast-radius standpoint.

@riaankleinhans
Copy link
Contributor

riaankleinhans commented Jan 8, 2025

@evankanderson we have achieve a few things here already.

At the moment the OpenSSF-Robot must have OpenSSF GH enterprise level Admin access to execute the landscape workflow. Clearly that would not be ideal when issuing PATs for running other automation.
I will look into more fine grained roles for the OpenSSF Robot to be able to share PATs via 1Password without exposing all of the OpenSSF GH Enterprise. (I am open to advise on GH roles)

@rdimitrov
Copy link

In case we don't want to have a bot per project approach, would it work to create a fine-grained minimally-scoped PAT from OpenSSF-Robot and distribute the token through a vault in 1password shared only between the OpenSSF-Robot owner and the administrators of the project/org it is intended to use it? I can experiment to see if that would work for our use case and also figure out the minimal set of permissions for it.

@riaankleinhans
Copy link
Contributor

In case we don't want to have a bot per project approach, would it work to create a fine-grained minimally-scoped PAT from OpenSSF-Robot and distribute the token through a vault in 1password shared only between the OpenSSF-Robot owner and the administrators of the project/org it is intended to use it? I can experiment to see if that would work for our use case and also figure out the minimal set of permissions for it.

@rdimitrov that is the workflow I have in mind as well.
fine-grained minimally-scoped PAT & figure out the minimal set of permissions for it is the next steps.

@rdimitrov
Copy link

@rdimitrov that is the workflow I have in mind as well. fine-grained minimally-scoped PAT & figure out the minimal set of permissions for it is the next steps.

Alright, I can take this action item with regards to Minder

@rdimitrov
Copy link

The following are the type of token and the minimum set of permissions needed for publishing to winget:

  • The token needs to be of type classic (not fine-grained; it doesn't work with it as it's supposed to be scoped to an org or repo from a given org and in this case we want to access microsoft/winget-pkgs)
Image
  • The permissions needed are only repo:public_repo (everything else should be un-ticked)
Image

cc: @adityasaky @evankanderson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants