Skip to content

Commit

Permalink
warehouse, tests: add and test ExpiryCaveat
Browse files Browse the repository at this point in the history
  • Loading branch information
woodruffw committed Apr 12, 2022
1 parent 9a84e62 commit 1f65cff
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
59 changes: 58 additions & 1 deletion tests/unit/macaroons/test_caveats.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@
# limitations under the License.

import json
import time

import pretend
import pytest

from pymacaroons.exceptions import MacaroonInvalidSignatureException

from warehouse.macaroons.caveats import Caveat, InvalidMacaroonError, V1Caveat, Verifier
from warehouse.macaroons.caveats import (
Caveat,
ExpiryCaveat,
InvalidMacaroonError,
V1Caveat,
Verifier,
)

from ...common.db.packaging import ProjectFactory

Expand Down Expand Up @@ -95,6 +102,56 @@ def test_verify_project(self, db_request):
assert caveat(json.dumps(predicate)) is True


class TestExpiryCaveat:
@pytest.mark.parametrize(
"predicate",
[
# invalid JSON
"invalid json",
# missing nbf and exp
'{"missing": "values"}',
# nbf and exp present, but null
'{"nbf": null, "exp": null}',
# nbf and exp present, but empty
'{"nbf": "", "exp": ""}',
# valid JSON, but wrong type
"[]",
],
)
def test_verify_invalid_predicates(self, predicate):
verifier = pretend.stub()
caveat = ExpiryCaveat(verifier)

assert not caveat(predicate)

def test_verify_not_before(self):
verifier = pretend.stub()
caveat = ExpiryCaveat(verifier)

not_before = int(time.time()) + 60
expiry = not_before + 60
predicate = json.dumps({"exp": expiry, "nbf": not_before})
assert not caveat(predicate)

def test_verify_already_expired(self):
verifier = pretend.stub()
caveat = ExpiryCaveat(verifier)

not_before = int(time.time()) - 10
expiry = not_before - 5
predicate = json.dumps({"exp": expiry, "nbf": not_before})
assert not caveat(predicate)

def test_verify_ok(self):
verifier = pretend.stub()
caveat = ExpiryCaveat(verifier)

not_before = int(time.time()) - 10
expiry = int(time.time()) + 60
predicate = json.dumps({"exp": expiry, "nbf": not_before})
assert caveat(predicate)


class TestVerifier:
def test_creation(self):
macaroon = pretend.stub()
Expand Down
21 changes: 21 additions & 0 deletions warehouse/macaroons/caveats.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# limitations under the License.

import json
import time

import pymacaroons

Expand Down Expand Up @@ -73,6 +74,25 @@ def verify(self, predicate):
return self.verify_projects(projects)


class ExpiryCaveat(Caveat):
def verify(self, predicate):
try:
data = json.loads(predicate)
expiry = data["exp"]
not_before = data["nbf"]
except (KeyError, ValueError, TypeError):
return False

if not expiry or not not_before:
return False

now = int(time.time())
if now < not_before or now >= expiry:
return False

return True


class Verifier:
def __init__(self, macaroon, context, principals, permission):
self.macaroon = macaroon
Expand All @@ -83,6 +103,7 @@ def __init__(self, macaroon, context, principals, permission):

def verify(self, key):
self.verifier.satisfy_general(V1Caveat(self))
self.verifier.satisfy_general(ExpiryCaveat(self))

try:
return self.verifier.verify(self.macaroon, key)
Expand Down

0 comments on commit 1f65cff

Please sign in to comment.