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

Warn users when GitHub/GitLab environments are not checked during Trusted Publishing #17281

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

facutuesca
Copy link
Contributor

@facutuesca facutuesca commented Dec 14, 2024

What is this?

This PR adds two things:

  1. Allow users to constrain the environment of an existing GitHub/GitLab Trusted Publisher.
    This means changing a publisher that allows any environment so that it only accepts one.
  2. Send project owners an email when a Trusted Publisher that allows any environment is used within a specific GitHub/GitLab environment
    The email suggests constraining the Trusted Publisher so that it only accepts the environment which was just used. The email also contains a link to the PyPI page to constrain the environment to the one used, so that project owners can just follow this link and confirm the change.

This fixes #17241

Details

UI/UX

  • The UI to constrain the environment can only be accessed via a URL like the following:
https://pypi.org/manage/project/$MY_PROJECT/settings/publishing/?constrained_publisher_id=$PUBLISHER_ID&constrained_environment=$NEW_ENVIRONMENT_NAME#constrain_environment-modal
  • That URL is the one included in the email, and it shows the following confirmation modal:
image
  • Constraining the environment will only work if all of the following are true:
    • The logged-in user is an owner (has write permissions) for $MY_PROJECT
    • The Trusted Publisher with ID $PUBLISHER_ID is a valid GitHub/GitLab publisher with no configured environment
    • The Trusted Publisher is associated to $MY_PROJECT
  • Internally, constraining the environment first creates a new TP which is a copy of the original one except for the new environment. Then, it removes the association between the original TP and the project. If this project was the only one associated to the original TP, the TP is deleted.

Email

  • The email is sent only when all of the following are true:
    • An OIDC token is exchanged for a PyPI token using a GitHub/GitLab Trusted Publisher
    • The Trusted Publisher is configured to accept any environment
    • The OIDC token contains a non-empty GitHub/GitLab environment claim
    • The Trusted Publisher is associated to only one project**

** This is done in order to avoid confusion and edge cases: if a single Trusted Publisher is configured for multiple projects, to send an email during the token exchange we would need to send it to the owners of all the projects, which might be confusing if the token exchange was for the upload of a single project's release.

Screenshots

Email

image

Confirmation modal

image

Action successful

image

cc @woodruffw @sethmlarson @di

@facutuesca facutuesca requested a review from a team as a code owner December 14, 2024 00:19
@facutuesca facutuesca changed the title Ft/constrain tp environment Warn users when Trusted Publisher allowing any environment is used with one Dec 14, 2024
@facutuesca facutuesca changed the title Warn users when Trusted Publisher allowing any environment is used with one Warn users when GitHub/GitLab environments are not checked during Trusted Publishing Dec 14, 2024
Comment on lines 1473 to 1526
# First we add the new trusted publisher
if isinstance(publisher, GitHubPublisher):
constrained_publisher = GitHubPublisher(
repository_name=publisher.repository_name,
repository_owner=publisher.repository_owner,
repository_owner_id=publisher.repository_owner_id,
workflow_filename=publisher.workflow_filename,
environment=form.constrain_environment.data,
)
elif isinstance(publisher, GitLabPublisher):
constrained_publisher = GitLabPublisher(
namespace=publisher.namespace,
project=publisher.project,
workflow_filepath=publisher.workflow_filepath,
environment=form.constrain_environment.data,
)

else:
self.request.session.flash(
"Can only constrain the environment for GitHub and GitLab publishers",
queue="error",
)
return self.default_response

if publisher.environment != "":
self.request.session.flash(
"Can only constrain the environment for publishers without an "
"environment configured",
queue="error",
)
return self.default_response

self.request.db.add(constrained_publisher)
self.request.db.flush() # ensure constrained_publisher.id is available
self.project.oidc_publishers.append(constrained_publisher)

self.project.record_event(
tag=EventTag.Project.OIDCPublisherAdded,
request=self.request,
additional={
"publisher": constrained_publisher.publisher_name,
"id": str(constrained_publisher.id),
"specifier": str(constrained_publisher),
"url": constrained_publisher.publisher_url(),
"submitted_by": self.request.user.username,
},
)

# Then, we remove the old trusted publisher from the project
# and, if there are no projects left associated with the publisher,
# we delete it entirely.
self.project.oidc_publishers.remove(publisher)
if len(publisher.projects) == 0:
self.request.db.delete(publisher)
Copy link
Member

Choose a reason for hiding this comment

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

I might be missing something, but can we simplify this by modifying the publisher rather than creating a new one and deleting the old one?

Copy link
Contributor Author

@facutuesca facutuesca Dec 14, 2024

Choose a reason for hiding this comment

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

It wouldn't cover the case where the publisher is associated to more than one project: since the magic link is associated to a single project, it should only affect that project. And modifying a publisher would modify it for all associated projects.

Copy link
Member

Choose a reason for hiding this comment

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

Ah right, completely forgot about that case! It might be good to leave a comment to that effect (the current comment explains it indirectly, but an explicit one might stop an over-eager refactor 🙂)

@facutuesca facutuesca requested review from di and woodruffw January 7, 2025 23:10
@woodruffw woodruffw added email Related to emails trusted-publishing labels Jan 8, 2025
Copy link
Member

@di di left a comment

Choose a reason for hiding this comment

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

LGTM otherwise

warehouse/templates/manage/project/publishing.html Outdated Show resolved Hide resolved
Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>
Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>
Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>
Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>
@facutuesca facutuesca force-pushed the ft/constrain-tp-environment branch from 5b0a592 to 81716d2 Compare January 10, 2025 19:00
Co-authored-by: Dustin Ingram <di@users.noreply.github.com>
@facutuesca facutuesca force-pushed the ft/constrain-tp-environment branch from 81716d2 to 3f3f993 Compare January 10, 2025 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Warning or error for Trusted Publisher users when GitHub Environment claim is included but not checked
3 participants