@@ -64,26 +64,50 @@ then from the database, the key and user are extracted. The macaroon is checked
64
64
the key and caveats are checked against the upload information. If the macaroon is
65
65
valid, then PyPI checks if the user has upload rights on the package, and then proceeds.
66
66
67
- The caveats are json-encoded strings, and as of May 2022, they come in 3 flavors:
68
-
69
- - ``"{"version": 1, "permissions": "user"}" `` (note: it's the string ``"user" `` here,
70
- not a placeholder for the username), which is always met. It's represented in this
71
- library by the class `NoopRestriction `,
72
- - ``"{"version": 1, "permissions": {"projects": ["<project name>", ...]}}" `` (note:
73
- ``"<project name>" `` is a placeholder here). It's met if the project we upload
74
- is among the ones listed in the caveats. It's represented by the
75
- `ProjectsRestriction `.
76
- - ``"{"nbf": <timestamp>, "exp": <timestamp>}" ``. It's met if we try uploading
77
- the project between ``nbf `` (included) and ``exp `` (excluded). It's
78
- represented by the
79
- `DateRestriction `.
80
-
81
- The projects restriction that PyPI implements is limited to:
82
-
83
- - a single project per token (even if the restriction format allows multiple projects)
84
- - creating tokens for existing projects you own (even though it's perfectly possible
85
- to create tokens for projects that don't exist yet, or for which you don't have
86
- upload permission yet).
67
+ The caveats are json-encoded strings, and as of October 2022, they come in 7 flavors:
68
+ 4 new caveats and 3 legacy caveats.
69
+ The legacy caveat are represented by classes prefixed by ``Legacy ``.
70
+
71
+ The types of caveats are:
72
+
73
+ - ``[0, <timestamp: int>, <timestamp: int>] `` is met if we try uploading the
74
+ project between ``nbf `` (included) and ``exp `` (excluded). It's represented
75
+ by the class `DateRestriction `. Legacy format is ``"{"nbf": <timestamp: int>,
76
+ "exp": <timestamp: int>}" `` and the corresponding class is
77
+ `LegacyDateRestriction `.
78
+
79
+ - ``[1, [<project_name: str>, ...]] `` is met if the project we upload is among
80
+ the ones listed in the caveats. It's represented by the class
81
+ `ProjectNamesRestriction `. Legacy format is ``{"version": 1, "permissions":
82
+ {"projects": [<project_name: str>, ...]}} `` and the corresponding class is
83
+ `LegacyProjectNamesRestriction `.
84
+
85
+ - ``[2, [<project_id: str>, ...]] `` is met if the project we upload is among
86
+ the ones listed in the caveats. It's represented by the class
87
+ `ProjectIDsRestriction `. There is no legacy equivalent.
88
+
89
+ - ``[3, <user_id: str>] `` is met if the user triggering the upload is the
90
+ one associated whit that UUID. It's represented by the class
91
+ `UserIDRestriction `
92
+
93
+ - ``{"version": 1, "permissions": "user"} `` which is always met. It's
94
+ represented in this library by the class `LegacyNoopRestriction `.
95
+
96
+ Within the PyPI website as of October 2022, one may generate tokens. Those tokens are
97
+ either associated with a single project or with the how account.
98
+
99
+ If they are associated to a single project, they will come with a
100
+ `ProjectNamesRestriction ` with a single value (the normalized name of the project)
101
+ and a `ProjectIDsRestriction ` with a single value (the ID if the project).
102
+
103
+ If they are not associated with a project, they will come with a `UserIDRestriction `
104
+ associated with the user who generated the token.
105
+
106
+ If they were generated before August 2022, they may come with legacy restrictions.
107
+
108
+ There is currently no way in the website's interface to generate tokens with
109
+ a `DateRestriction ` or associated with multiple projects, but if such a token
110
+ was received, PyPI would interpret it correctly.
87
111
88
112
.. note ::
89
113
@@ -93,27 +117,27 @@ The projects restriction that PyPI implements is limited to:
93
117
Do we really need an abstraction layer over PyMacaroons?
94
118
--------------------------------------------------------
95
119
96
- Yes ? No ? Maybe ? What's clear is that the implementation in PyPI is adding some
97
- unnecessary complexity, and the community would benefit from a single source of
98
- macaroons, so that the same codebase will be responsible for serializing and
99
- deserializing the custom PyPI token restrictions.
120
+ Yes ? No ? Maybe ? What's clear is that the community would benefit from a
121
+ single source of macaroons, so that the same codebase would be responsible for
122
+ serializing and deserializing the custom PyPI token restrictions.
100
123
101
124
Can we add new restrictions?
102
125
----------------------------
103
126
104
- As long as PyPI doesn't use ``pypitoken `` to generate tokens, it's not very useful
105
- to implement new restrictions. But once we get it merged, then we'll want to add plenty
106
- of new and smart restrictions (based on time, upload file name and hash, etc)
127
+ As long as PyPI doesn't use ``pypitoken `` to generate tokens, it's not very
128
+ useful to implement new restrictions here that would not already be supported
129
+ by PyPI. We're doing our best to have this library follow developments of PyPI
130
+ itself, and provide feature-parity.
107
131
108
- The restrictions planned for the future are:
132
+ In discussions around PyPI development, the following restrictions that have
133
+ been mentionned:
109
134
110
135
- Version-based restriction
111
136
- Filename-based restriction
112
137
- Hash-sum-based restriction
113
138
- IP-based restriction
114
139
- One-time-use restriction (this will require Warehouse to remember a value)
115
140
- Somehow restricting to uploads coming from a given project's CI
116
- - ...? (ideas welcome)
117
141
118
142
Most of those were initially discussed in the `Warehouse tracker `__.
119
143
@@ -132,10 +156,10 @@ Is this library a part of PyPI?
132
156
It's being developper externally. The initiator of this project is a member of the
133
157
Python Packaging Authority (PyPA) and PyPI moderator, but not an admin nor a committer.
134
158
135
- As of today, the library is not part of the PyPA. Once this lib is done, it's planned
136
- to apply for this lib to be added to PyPA.
159
+ There was an offer __ for this library to be adopted by PyPA, but it didn't gain any
160
+ traction
137
161
138
- .. _ Macaroon recipe :
162
+ .. __ : https://discuss.python.org/t/pypitoken-a-library-for-generating-and-manipulating-pypi-tokens/7572
139
163
140
164
Why is there a noop restriction?
141
165
--------------------------------
@@ -144,32 +168,20 @@ Good question. The author is not sure either. In the original discussions in War
144
168
the idea was to have 2 types of tokens: "user" tokens and "projects" tokens. But even
145
169
without restrictions, tokens are already scoped to a specific user, so adding a "user"
146
170
restriction actually changes nothing, thus why it's implemented in ``pypitoken `` as a
147
- `NoopRestriction `.
171
+ `LegacyNoopRestriction `.
148
172
149
- Though it's not been tested yet, tokens without restrictions should work the same
150
- as tokens with a noop restriction (or, for what it's worth, token with multiple noop
151
- restrictions).
152
-
153
- Should we have multiple restrictions in a single caveat?
154
- --------------------------------------------------------
173
+ Tokens without restrictions work the same as tokens with a noop restriction
174
+ (or, for what it's worth, token with multiple noop restrictions).
155
175
156
- This is a real question we may encounter when we'll have multiple types of restrictions:
157
- when we want to apply a restriction to multiple aspects, should we implement all of them
158
- in a single caveat modelling all the aspects, or should each restriction be its own
159
- caveat?
160
-
161
- It can be noted that "user" (noop) restrictions and "projects" restrictions are not
162
- compatible, so this would tend to indicate it was not planned for multiple restrictions
163
- to be grouped into a single caveat.
164
-
165
- Having multiple restrictions in a single json payload makes it harder to check whether
166
- it's valid or not (at least, while the general format of the json payloads is not
167
- unified). No definitive answer is given at this time.
176
+ Note that when the restrictions were re-worked in PyPI in Summer 2022, the
177
+ "user" caveat was actually associated with a check that the request was
178
+ originated by the corresponding user. This is mainly relevant around OpenID
179
+ Connect use-cases.
168
180
169
181
What does "normalized name" mean?
170
182
---------------------------------
171
183
172
- Throughout the doc, the term "normalized name" for a project is regularily used.
184
+ Throughout the doc, the term "normalized name" for a project is regularly used.
173
185
This is because some characters are synonymous in a project name, so in order to match
174
186
a project name, we need to put it to canonical form first.
175
187
@@ -206,6 +218,8 @@ Adding restrictions yourself on existing tokens have consequences on those eleme
206
218
This way, your PyPI account page will still be a good place to track all of your
207
219
existing tokens, and you will be able to follow each of them easily.
208
220
221
+ .. _Macaroon recipe :
222
+
209
223
All this talking about Macaroons, I'm hungry now!
210
224
-------------------------------------------------
211
225
@@ -222,12 +236,12 @@ Ingredients:
222
236
Steps:
223
237
224
238
1. Preheat oven to 50°C.
225
- 2. Spread the gound almonds on a baking sheet, put in oven for 10 to 15 minutes.
239
+ 2. Spread the ground almonds on a baking sheet, put in oven for 10 to 15 minutes.
226
240
3. Remove it from oven, let it cool and mix with sugar.
227
241
4. Whip the egg whites stiff and add a few drops of bitter almond.
228
242
5. Using a rubber spatula, fold the egg whites into the sugar & almond batter.
229
243
6. Pour the batter into a piping bag with a ribbed nozzle.
230
- 7. Form the macaroons on baking paper and leave them to rest for 2h at ambiant
244
+ 7. Form the macaroons on baking paper and leave them to rest for 2h at ambient
231
245
temperature.
232
246
8. Preheat oven to 190°C.
233
247
9. Lower the oven to 180°C, and put the macaroons in for 3 minutes, then 15 minutes at
0 commit comments