Skip to content

Commit

Permalink
Fix GitLab Trusted Publishers UI and docs (#15921)
Browse files Browse the repository at this point in the history
Change the "workflow file path" field in the UI and in the docs to
"top-level pipeline file path". This is the correct term, since
GitLab OIDC claims only provide the top-level pipeline (usually
`.gitlab-ci.yml`), rather than individual jobs/workflows.

Also change the security model doc, to clarify that PyPI cannot
tell the difference between different .yml files that are included
in `.gitlab-ci.yml`, since it's the latter that is reported in
the claims.
  • Loading branch information
facutuesca authored May 7, 2024
1 parent 3214ace commit c0f7789
Show file tree
Hide file tree
Showing 12 changed files with 43 additions and 42 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions docs/user/trusted-publishers/adding-a-publisher.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ each.
instances are not supported.

For GitLab CI/CD, you **must** provide the repository's namespace, the
repository's name, and the filepath of the GitLab CI/CD workflow that's
authorized to upload to PyPI. In addition, you may **optionally**
provide the name of a
repository's name, and the filepath of the top-level GitLab CI/CD pipeline
definition that's authorized to upload to PyPI. In addition, you may
**optionally** provide the name of a
[GitLab CI/CD environment](https://docs.gitlab.com/ee/ci/environments/).

For example, if you have a project at `https://gitlab.com/namespace/sampleproject`
that uses a publishing workflow defined in `release.yml` and a custom
environment named `release`, then you'd do the following:
with a top-level pipeline defined in `.gitlab-ci.yml` and a custom environment
named `release`, then you'd do the following:

![Image showing adding a new GitLab publisher](/assets/trusted-publishing/gitlab/project-publishing-form.png)

Expand All @@ -135,7 +135,7 @@ each.

![Image showing a newly added GitLab publisher](/assets/trusted-publishing/gitlab/project-publisher-registered.png)

From this point onwards, the `release.yml` workflow on `namespace/sampleproject`
From this point onwards, the `.gilab-ci.yml` pipeline on `namespace/sampleproject`
will be able to generate short-lived API tokens from PyPI for the project you've
registered it against.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ provide the name of the PyPI project that will be created.
instances are not supported.

If you have a repository at
`https://gitlab.com/namespace/sampleproject` with a release workflow at
`release.yml` and an environment named `release` that you would like to publish
`https://gitlab.com/namespace/sampleproject` with a top-level pipeline defined in
`.gitlab-ci.yml` and an environment named `release` that you would like to publish
to PyPI as `sampleproject`, then you would do the following:

![Image showing adding a new GitLab publisher](/assets/trusted-publishing/gitlab/pending-publisher-form-filled.png)
Expand Down
29 changes: 14 additions & 15 deletions docs/user/trusted-publishers/security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ own security model and considerations.
[`id_tokens`](https://docs.gitlab.com/ee/ci/yaml/index.html#id_tokens) keyword,
along with the desired audience. The tokens are made available through
environment variables when the job runs.
* The claims defined in an OIDC token are *bound to the workflow*, meaning
that a workflow defined at `foo.yml` in `org/repo` **cannot impersonate**
a workflow defined at `bar.yml` in `org/repo`. However, if `foo.yml` is
*renamed* to `bar.yml`, then the *new* `bar.yml` will be indistinguishable
from the old `bar.yml` **except** for claims that reflect the repository's
state (e.g. `git` ref, branch, etc.).
* An OIDC token for a specific repository and workflow can be generated by anyone
who has permissions to run that workflow in the repository's CI/CD.
* The claims defined in an OIDC token are *bound to the group and project*, meaning that a
repository located at orgA/repo cannot impersonate a repository located at orgB/repo.
* The claims defined in an OIDC token are *bound to the top-level pipeline*, meaning
that any pipeline included by the top-level pipeline (usually `.gitlab-ci.yml`)
will be able to upload using a trusted publisher that trusts the `.gitlab-ci.yml`
pipeline.
* An OIDC token for a specific repository and pipeline can be generated by anyone
who has permissions to run that pipeline in the repository's CI/CD.

<h3>Considerations</h3>

Expand All @@ -203,14 +203,13 @@ own security model and considerations.
username or group is deleted and a new one with the same name is created,
PyPI will still recognise OIDC tokens generated by the new one as valid.

* Trust the correct workflow: you shouldn't trust every workflow
to upload to PyPI; instead, you should isolate responsibility to the
smallest (and least-privileged) possible separate workflow. We recommend
naming this workflow `release.yml`.

* Take care when merging third-party changes to your code: if you trust
`release.yml`, then you must make sure that third-party changes to that
workflow (or code that runs within that workflow) are not malicious.
the top-level pipeline `.gitlab-ci.yml`, then you must make sure that
third-party changes to that file are not malicious. This is particularly
important since GitLab does not provide granular information about which
job requested the token: only the top-level pipeline is included in the
claims, which means that any job run by the top-level pipeline can request
a valid OIDC token.

* Take care when adding repository contributors, members, and administrators:
by default, anybody who can unconditionally commit to your repository can
Expand Down
22 changes: 11 additions & 11 deletions warehouse/locale/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -685,20 +685,20 @@ msgstr ""
msgid "Invalid GitLab username or group/subgroup name."
msgstr ""

#: warehouse/oidc/forms/gitlab.py:53
msgid "Specify workflow filepath"
#: warehouse/oidc/forms/gitlab.py:54
msgid "Specify top-level pipeline file path"
msgstr ""

#: warehouse/oidc/forms/gitlab.py:61
#: warehouse/oidc/forms/gitlab.py:63
msgid "Invalid environment name"
msgstr ""

#: warehouse/oidc/forms/gitlab.py:76
msgid "Workflow file path must end with .yml or .yaml"
#: warehouse/oidc/forms/gitlab.py:78
msgid "Top-level pipeline file path must end with .yml or .yaml"
msgstr ""

#: warehouse/oidc/forms/gitlab.py:80
msgid "Workflow file path cannot start or end with /"
#: warehouse/oidc/forms/gitlab.py:82
msgid "Top-level pipeline file path cannot start or end with /"
msgstr ""

#: warehouse/packaging/forms.py:27
Expand Down Expand Up @@ -4534,7 +4534,7 @@ msgstr ""

#: warehouse/templates/manage/account/publishing.html:202
#: warehouse/templates/manage/project/publishing.html:170
msgid "Workflow file path"
msgid "Top-level pipeline file path"
msgstr ""

#: warehouse/templates/manage/account/publishing.html:207
Expand All @@ -4545,9 +4545,9 @@ msgstr ""
#: warehouse/templates/manage/account/publishing.html:209
#: warehouse/templates/manage/project/publishing.html:177
msgid ""
"The file path of the publishing workflow, relative to the project's root."
" This file should exist in the project configured above (external "
"workflows are not supported)."
"The file path of the top-level pipeline, relative to the project's root. "
"This file should exist in the project configured above (external "
"pipelines are not supported)."
msgstr ""

#: warehouse/templates/manage/account/publishing.html:226
Expand Down
8 changes: 5 additions & 3 deletions warehouse/oidc/forms/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ class GitLabPublisherBase(forms.Form):

workflow_filepath = wtforms.StringField(
validators=[
wtforms.validators.InputRequired(message=_("Specify workflow filepath"))
wtforms.validators.InputRequired(
message=_("Specify top-level pipeline file path")
)
]
)

Expand All @@ -73,11 +75,11 @@ def validate_workflow_filepath(self, field):
workflow_filepath.endswith(".yml") or workflow_filepath.endswith(".yaml")
):
raise wtforms.validators.ValidationError(
_("Workflow file path must end with .yml or .yaml")
_("Top-level pipeline file path must end with .yml or .yaml")
)
if workflow_filepath.startswith("/") or workflow_filepath.endswith("/"):
raise wtforms.validators.ValidationError(
_("Workflow file path cannot start or end with /")
_("Top-level pipeline file path cannot start or end with /")
)

@property
Expand Down
4 changes: 2 additions & 2 deletions warehouse/templates/manage/account/publishing.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,14 @@
</div>
<div class="form-group">
<label for="workflow_filepath" class="form-group__label">
{% trans %}Workflow file path{% endtrans %}
{% trans %}Top-level pipeline file path{% endtrans %}
{% if pending_gitlab_publisher_form.workflow_filepath.flags.required %}
<span class="form-group__required">{% trans %}(required){% endtrans %}</span>
{% endif %}
</label>
{{ pending_gitlab_publisher_form.workflow_filepath(placeholder=gettext(".gitlab-ci.yml"), class_="form-group__field", autocomplete="off", **{"aria-describedby":"workflow_filepath-errors"}) }}
<p class="form-group__help-text">
{% trans %}The file path of the publishing workflow, relative to the project's root. This file should exist in the project configured above (external workflows are not supported).{% endtrans %}
{% trans %}The file path of the top-level pipeline, relative to the project's root. This file should exist in the project configured above (external pipelines are not supported).{% endtrans %}
</p>
<div id="workflow_filepath-errors">
{{ field_errors(pending_gitlab_publisher_form.workflow_filepath) }}
Expand Down
2 changes: 1 addition & 1 deletion warehouse/templates/manage/manage_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ <h3 class="modal__title">{{ title }}</h3>
{% endif %}
{% elif publisher.publisher_name == "GitLab" %}
<b>Project:</b> <a href="{{ publisher.publisher_url() }}">{{ publisher.project_path }}</a><br>
<b>Workflow:</b> {{ publisher.workflow_filepath }}<br>
<b>Top-level pipeline:</b> {{ publisher.workflow_filepath }}<br>
<b>Environment name:</b>
{% if publisher.environment %}
{{ publisher.environment }}
Expand Down
4 changes: 2 additions & 2 deletions warehouse/templates/manage/project/publishing.html
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@
</div>
<div class="form-group">
<label for="workflow_filepath" class="form-group__label">
{% trans %}Workflow file path{% endtrans %}
{% trans %}Top-level pipeline file path{% endtrans %}
{% if gitlab_publisher_form.workflow_filepath.flags.required %}
<span class="form-group__required">{% trans %}(required){% endtrans %}</span>
{% endif %}
</label>
{{ gitlab_publisher_form.workflow_filepath(placeholder=gettext(".gitlab-ci.yml"), class_="form-group__field", autocomplete="off", **{"aria-describedby":"workflow_filepath-errors"}) }}
<p class="form-group__help-text">
{% trans %}The file path of the publishing workflow, relative to the project's root. This file should exist in the project configured above (external workflows are not supported).{% endtrans %}
{% trans %}The file path of the top-level pipeline, relative to the project's root. This file should exist in the project configured above (external pipelines are not supported).{% endtrans %}
</p>
<div id="workflow_filepath-errors">
{{ field_errors(gitlab_publisher_form.workflow_filepath) }}
Expand Down

0 comments on commit c0f7789

Please sign in to comment.