Skip to content

Trusted publishing: Support for GitHub reusable workflows #11096

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

Open
woodruffw opened this issue Apr 1, 2022 · 34 comments
Open

Trusted publishing: Support for GitHub reusable workflows #11096

woodruffw opened this issue Apr 1, 2022 · 34 comments
Assignees
Labels
feature request security Security-related issues and pull requests trusted-publishing

Comments

@woodruffw
Copy link
Member

Our MVP implementation (#10753) assumes that the workflow is in the same repository, which is not necessarily true.

We should support reusable workflows, specifically via the job_workflow_ref claim.

@woodruffw
Copy link
Member Author

Just as a note: this will have to interoperate with #11263.

@GergelyKalmar
Copy link

Any chance to expedite this issue? It seems there's many who would be eager to move over to trusted publishing now that it is the recommended approach, but not being able to do the flow from a reusable workflow is a pretty major blocker. This issue also does not seem to be documented anywhere so we only find out about it once we changed everything to use the new approach.

@woodruffw
Copy link
Member Author

Any chance to expedite this issue?

I can't personally promise a timeline here, but it is on my backlog of things to do.

This issue also does not seem to be documented anywhere so we only find out about it once we changed everything to use the new approach.

Thank you for pointing this out; I'll make some changes to the docs to emphasize that reusable workflows are not currently supported.

@woodruffw
Copy link
Member Author

Thank you for pointing this out; I'll make some changes to the docs to emphasize that reusable workflows are not currently supported.

I've opened #13592 for this. Thanks again for bringing it to our attention!

@di di changed the title Support for OIDC publishing from reusable workflows Trusted publishing: Support for GitHub reusable workflows Jun 7, 2023
mhils added a commit to mitmproxy/mitmproxy_rs that referenced this issue Jun 13, 2023
mhils added a commit to mhils/workflows that referenced this issue Jun 13, 2023
h3mmy added a commit to tyg3rr/Epi_Helper that referenced this issue Jun 25, 2023
h3mmy added a commit to tyg3rr/Epi_Helper that referenced this issue Jun 25, 2023
Switch to using API Token pending pypi/warehouse#11096
@webknjaz
Copy link
Member

@woodruffw I just stumbled upon an example of a reusable workflow actually working with OIDC here jorisroovers/gitlint#486 — could you confirm this is because of secrets: inherit at https://github.com/jorisroovers/gitlint/blob/5247839/.github/workflows/ci.yml#L225 ?

@GergelyKalmar
Copy link

GergelyKalmar commented Jun 29, 2023

That workflow is in the same repository though, I think the issue is with reusable workflows that are in a different repository (e.g. in a separate public repo).

@woodruffw
Copy link
Member Author

Yeah, I think that's because it's in the same repo, not because of secrets: inherit.

In other words: reusable workflows do work with the current implementation, just not reusable workflows that are external to the repository that the trusted publisher was configured with.

@webknjaz
Copy link
Member

That workflow is in the same repository though, I think the issue is with reusable workflows that are in a different repository (e.g. in a separate public repo).

Yes, you can't use inherit across orgs. The issue was that the OIDC context has a reusable workflow reference and that's currently not checked IIUC. So my concern is that it might be possible to fool the verification logic in PyPI with this...

@GergelyKalmar
Copy link

You can get around the inherit issue between organizations via forking, which is what we would usually do. So same org, different repo would be fine. The point of reusable workflows in this case would be that you store them in a central repository and you can re-use them in other repositories.

@webknjaz
Copy link
Member

webknjaz commented Jun 29, 2023

I also wonder if it's possible to do something like

secrets:
  GITHUB_TOKEN: ${{ github.token }}

to make OIDC in the reusable workflow pretend to be the called workflow...

subrat-lima pushed a commit to subrat-lima/yt-dlp that referenced this issue Mar 31, 2025
frankinspace pushed a commit to MAAP-Project/algorithms-jupyter-extension that referenced this issue Apr 2, 2025
frankinspace pushed a commit to MAAP-Project/che-sidebar-visibility-jupyter-extension that referenced this issue Apr 2, 2025
frankinspace pushed a commit to MAAP-Project/che-sidebar-visibility-jupyter-extension that referenced this issue Apr 2, 2025
frankinspace pushed a commit to MAAP-Project/dps-jupyter-extension that referenced this issue Apr 2, 2025
carlcsaposs-canonical added a commit to canonical/data-platform-workflows that referenced this issue Apr 28, 2025
Unable to use reusable workflow with trusted publishing
pypi/warehouse#11096

Using trusted publishing in a composite action is also not supported https://github.com/marketplace/actions/pypi-publish#non-goals
carlcsaposs-canonical added a commit to canonical/data-platform-workflows that referenced this issue Apr 28, 2025
Unable to use reusable workflow with trusted publishing
pypi/warehouse#11096

Using trusted publishing in a composite action is also not supported https://github.com/marketplace/actions/pypi-publish#non-goals
carlcsaposs-canonical added a commit to canonical/data-platform-workflows that referenced this issue Apr 28, 2025
Unable to use reusable workflow with trusted publishing
pypi/warehouse#11096

Using trusted publishing in a composite action is also not supported https://github.com/marketplace/actions/pypi-publish#non-goals
carlcsaposs-canonical added a commit to canonical/data-platform-workflows that referenced this issue Apr 28, 2025
Unable to use reusable workflow with trusted publishing
pypi/warehouse#11096

Using trusted publishing in a composite action is also not supported https://github.com/marketplace/actions/pypi-publish#non-goals
@jaraco
Copy link
Contributor

jaraco commented May 11, 2025

It sounds like the progress here is going in a direction that's not going to help me (and thus trusted publishing will be out of reach indefinitely). I've developed a system for managing software with the value proposition being that one can maintain packages without having to copy/paste the system-wide configuration (CI config) to each project. So the project uses a minimal project-repo-level config (example) that links into a system-wide config that includes the release hook. So when something needs to change at the system level (such as it has several times in the past few months), those changes automatically reflect in the enrolled repos. It wouldn't be suitable for these repos to pin to the shared workflow, because that would defeat the purpose of streamlining the maintenance and would require a commit to each of hundreds of repos each time the system definition needed a tweak.

Do I understand correctly that the planned support for trusted repos for reusable workflows is going to require that the reusable workflow be pinned, and thus won't be suitable for the coherent system?

@woodruffw
Copy link
Member Author

Do I understand correctly that the planned support for trusted repos for reusable workflows is going to require that the reusable workflow be pinned, and thus won't be suitable for the coherent system?

I don't think the plan is to require a pin on the reusable workflow, no -- that's been floated as an idea for additionally constraining the Trusted Publisher (and asserting its hermetic properties), but the basic idea laid out in #11096 (comment) would allow reusable workflows to be configured without a pin, like normal workflow identities currently can be.

@ekohl
Copy link

ekohl commented May 12, 2025

For Ruby I ended up implementing a composite action: https://github.com/voxpupuli/ruby-release. This works because a composite action doesn't create a new context and you can generate an OIDC token.

@webknjaz
Copy link
Member

@ekohl it's important to physically separate jobs that build things from the job that publishes them. This is because giving elevated privileges to all the transitive deps in the build tool chain is usually a bad idea. Allowing OIDC in other contexts can lead to repo identity impersonation in systems beyond PyPI, which is why I've been actively discouraging that. And additionally, when we were optimizing the action, it ended up being a composite action wrapping a docker one. It turned out that GH doesn't work well with nested composite actions and various unexpected context leak into our env making it defunct. So I've been trying to heavily narrow down the scope of what's considered supported in the action: https://github.com/marketplace/actions/pypi-publish#Non-goals.

That said, I'm planning to make a reusable workflow under PyPA that people would be able to use w/o having to duplicate that within each of their projects. It wouldn't work until PyPI supports this, so I'm not in a hurry to start that just yet. But that workflow will implement what I consider secure practices, so others wouldn't have to think about it and only bring in their jobs that build their dists.

@ekohl
Copy link

ekohl commented May 12, 2025

@ekohl it's important to physically separate jobs that build things from the job that publishes them.

In my Ruby workflow I use plain gem build without installing any dependencies. All I need is ruby/setup-ruby which I'd also need for gem push. This is different than the Python ecosystem where you have many different implementations.

You can argue that I end up installing rubygems-await, which is pulling in some additional dependencies. And I suppose you could also separate the gem build into a separate job without credentials since you could run code via the gemspec. I'll think about that some more.

@webknjaz
Copy link
Member

You can argue that I end up installing rubygems-await, which is pulling in some additional dependencies. And I suppose you could also separate the gem build into a separate job without credentials since you could run code via the gemspec. I'll think about that some more.

I don't know Ruby enough, but it sounds similar to what PEP 517 build backends do. Hence, the same precautions apply. In the reusable workflow I'm thinking of, there'd be exactly 2 tasks — one to download pre-built dists and the second one to upload them. And nothing else, even remotely untrusted.

JCGoran added a commit to neuronsimulator/nrn that referenced this issue May 13, 2025
Due to pypi/warehouse#11096 one cannot use a
reusable workflow for uploading wheels to PyPI yet.
JCGoran added a commit to neuronsimulator/nrn that referenced this issue May 13, 2025
Due to pypi/warehouse#11096 one cannot use a
reusable workflow for uploading wheels to PyPI yet.
woodruffw added a commit to trail-of-forks/wg-securing-software-repos that referenced this issue May 17, 2025
TL;DR: `job_workflow_ref` and `workflow_ref` are
*often* the same thing and have the same value,
but sometimes diverge in ways that make later
support for GitHub's reusable workflows difficult.

This guide should recommend `workflow_ref` instead of
`job_workflow_ref` for the "baseline" of Trusted
Publishing, since it's always correct as the
"initiating" workflow identity.

See pypi/warehouse#11096
and rust-lang/crates.io#11131 (comment)
for more context.

Signed-off-by: William Woodruff <[email protected]>
steiza pushed a commit to ossf/wg-securing-software-repos that referenced this issue May 19, 2025
TL;DR: `job_workflow_ref` and `workflow_ref` are
*often* the same thing and have the same value,
but sometimes diverge in ways that make later
support for GitHub's reusable workflows difficult.

This guide should recommend `workflow_ref` instead of
`job_workflow_ref` for the "baseline" of Trusted
Publishing, since it's always correct as the
"initiating" workflow identity.

See pypi/warehouse#11096
and rust-lang/crates.io#11131 (comment)
for more context.

Signed-off-by: William Woodruff <[email protected]>
@facutuesca
Copy link
Contributor

Following IRL discussion with @miketheman , @webknjaz and @woodruffw , here's pseudocode for a potential migration path that adds support for publishing from a (top-level) workflow file that calls another (reusable) workflow file.

claim_top = "workflow_ref"
claim_bottom = "job_workflow_ref"
reusable_workflow_supported_date = "TBD" # date when this change is merged

if claim_top == claim_bottom:  # non-reusable workflow case
    tp_obj = query(TP, TP.filename == claim_top)
    if tp_obj:
        # exchange token
        pass
    else:
        raise TPNotFound()
if claim_top != claim_bottom:  # reusable workflow case
    # if claim_bottom != lastSecurityEvent.bottom: sendEmail()
    # securityEvent.record(TP, claim_bottom)
    tp_obj = query(TP, TP.filename == claim_top)

    if tp_obj:
        # logic for future support of constraining reusable workflow
        # if tp_obj.bottom_filename is None:
        #     # send email (optional)
        #     # exchange token
        #     pass
        # elif tp_obj.bottom_filename == claim_bottom:  # bottom_filename is an optional field
        #     # exchange token
        #     pass
        # elif tp_obj.bottom_filename != claim_bottom:
        #     raise TPNotFound()

        # exchange token
        pass

    else:
        # temporary support for migration purposes
        tp_obj_bottom = query(TP, TP.filename == claim_bottom AND TP.created_date < reusable_workflow_supported_date) 
        if not tp_obj_bottom:
            raise TPNotFound()
        else:
            # exchange token
            # send email about TP referring to reusable instead of top-level workflow
            pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request security Security-related issues and pull requests trusted-publishing
Projects
None yet
Development

No branches or pull requests

10 participants