Skip to content

Commit

Permalink
Merge pull request #94 from ewjoachim/expiry
Browse files Browse the repository at this point in the history
  • Loading branch information
ewjoachim committed May 29, 2022
2 parents 6e34d90 + 16dced9 commit abc0ec9
Show file tree
Hide file tree
Showing 9 changed files with 419 additions and 37 deletions.
10 changes: 6 additions & 4 deletions docs/discussions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ The specification doesn't say what the caveat strings should be, but the idea is
each caveat is adding a restriction to the original macaroon, so that when the bearer
has to send the macaroon, they only delegate the smallest fraction of their power.

It's up to the Macaroon original minter to decide how to understand the caveats,
but when they receive a macaroon for
It's up to the Macaroon original minter to decide how to understand the caveats.

.. _HMAC: https://en.wikipedia.org/wiki/HMAC

Expand Down Expand Up @@ -65,7 +64,7 @@ then from the database, the key and user are extracted. The macaroon is checked
the key and caveats are checked against the upload information. If the macaroon is
valid, then PyPI checks if the user has upload rights on the package, and then proceeds.

The caveats are json-encoded strings, and as of March 2021, they come in 2 flavors:
The caveats are json-encoded strings, and as of May 2022, they come in 3 flavors:

- ``"{"version": 1, "permissions": "user"}"`` (note: it's the string ``"user"`` here,
not a placeholder for the username), which is always met. It's represented in this
Expand All @@ -74,6 +73,10 @@ The caveats are json-encoded strings, and as of March 2021, they come in 2 flavo
``"<project name>"`` is a placeholder here). It's met if the project we upload
is among the ones listed in the caveats. It's represented by the
`ProjectsRestriction`.
- ``"{"nbf": <timestamp>, "exp": <timestamp>}"``. It's met if we try uploading
the project between ``nbf`` (included) and ``exp`` (excluded). It's
represented by the
`DateRestriction`.

The projects restriction that PyPI implements is limited to:

Expand Down Expand Up @@ -107,7 +110,6 @@ The restrictions planned for the future are:
- Version-based restriction
- Filename-based restriction
- Hash-sum-based restriction
- Time-window-based restriction
- IP-based restriction
- One-time-use restriction (this will require Warehouse to remember a value)
- Somehow restricting to uploads coming from a given project's CI
Expand Down
15 changes: 10 additions & 5 deletions docs/howto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ elsewhere.

Of course, just creating a macaroon with this library is not enough to have
it be valid on PyPI: valid macaroons need to exist in the database and this
library only handles the computation part, not the stroring part.
library only handles the computation part, not the storing part.

Create a token
--------------
Expand All @@ -123,10 +123,12 @@ Use `Token.create`, `Token.restrict`, `Token.dump`::
prefix="pypi",
)

# Use either
token.restrict(projects=["project-normalized-name"]) # project-specific token
# Or
# Use
token.restrict() # user-wide token
# Or
token.restrict(projects=["project-normalized-name"]) # project-specific token
# You can also restrict the token in time:
token.restrict(not_before=timestamp_or_tz_aware_dt, not_after=timestamp_or_tz_aware_dt)

token_to_display = token.dump()

Expand All @@ -151,7 +153,7 @@ Use `Token.load`, `Token.check`::

try:
# The project the user is currently uploading
token.check(project="project-normalize-name")
token.check(project="project-normalize-name", now=int(time.time()))
except pypitoken.ValidationError:
display_error(exc)
return Http403()
Expand All @@ -164,3 +166,6 @@ If you find a case where the exception is not as helpful as it should be, and yo
believe the program has more information but it was lost during the exception bubbling
phase, or if the information in the exception is not appropriate to be shown back to the
user, this will be considered a ``pypitoken`` bug, feel free to open an issue.

You may omit the ``now`` parameter in the `Token.check` call, it will default
to the current integer timestamp. That said, it's ok to be explicit.
6 changes: 6 additions & 0 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ should not have to call the methods directly. Use `Token.restrict` and
.. autoclass:: pypitoken.ProjectsRestriction
:show-inheritance:

.. autoclass:: pypitoken.DateRestriction
:show-inheritance:


Exceptions
----------
Expand All @@ -36,3 +39,6 @@ Exceptions

.. autoclass:: pypitoken.ValidationError
:show-inheritance:

.. autoclass:: pypitoken.InvalidRestriction
:show-inheritance:
17 changes: 15 additions & 2 deletions pypitoken/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
from .exceptions import LoaderError, PyPITokenException, ValidationError
from .token import NoopRestriction, ProjectsRestriction, Restriction, Token
from .exceptions import (
InvalidRestriction,
LoaderError,
PyPITokenException,
ValidationError,
)
from .token import (
DateRestriction,
NoopRestriction,
ProjectsRestriction,
Restriction,
Token,
)

__all__ = [
# Main classes
"Token",
"Restriction",
# Restriction subclasses
"DateRestriction",
"NoopRestriction",
"ProjectsRestriction",
# Exceptions
"PyPITokenException",
"InvalidRestriction",
"LoaderError",
"ValidationError",
]
7 changes: 7 additions & 0 deletions pypitoken/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ class PyPITokenException(Exception):
"""


class InvalidRestriction(PyPITokenException, ValueError):
"""
Exception encoutered while calling `Token.restrict`, due to unexpected
parameters.
"""


class LoaderError(PyPITokenException):
"""
Exception encoutered while calling `Token.load`, due to unexpected
Expand Down

0 comments on commit abc0ec9

Please sign in to comment.