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

One time use project upload token #6935

Closed
wants to merge 114 commits into from
Closed
Show file tree
Hide file tree
Changes from 102 commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
34f5e96
Psuedo code added for issue #6255.
rachelcipkins Aug 29, 2019
545dea0
Added caveats for project version and macaroon expiration time.
rachelcipkins Aug 30, 2019
cd4e8a2
Added tests for expiration time.
rachelcipkins Sep 5, 2019
03ea2ce
Updated caveats for expiration time and release.
rachelcipkins Sep 5, 2019
1447ed7
Added macaroon fields for expiration time and release.
rachelcipkins Sep 5, 2019
0d2733d
Added expiration field to macaroon.
rachelcipkins Sep 5, 2019
a89a25e
Added form fields for expiration and release.
rachelcipkins Sep 5, 2019
8826d39
Moved release caveat.
rachelcipkins Sep 6, 2019
d3cb195
Added potential new Macaroon fields.
rachelcipkins Sep 6, 2019
71f7c1b
Added scope, release, and expiration fields to Macaroon object.
rachelcipkins Sep 6, 2019
2e62cfc
Added scope, release, and expiration fields to create_macaroon.
rachelcipkins Sep 6, 2019
29dcb8c
Changed release to be a text input.
rachelcipkins Sep 6, 2019
0de8289
Updated validate_release.
rachelcipkins Sep 6, 2019
e96b1b0
Added verification for release.
rachelcipkins Sep 9, 2019
5cbadb0
Updated timezone info to GMT for POC.
rachelcipkins Sep 9, 2019
1913b28
Removed macaroon db fields for scope, release, and expiration. Added …
rachelcipkins Sep 9, 2019
b5bb8ce
Updated functionality for release caveat.
rachelcipkins Sep 10, 2019
63cfeee
Added validation for releases.
rachelcipkins Sep 10, 2019
77e80b0
Added property to macaroon views to get all of a user's projects.
rachelcipkins Sep 10, 2019
ece4724
Removed testing lines.
rachelcipkins Sep 10, 2019
c9feca4
Removed note.
rachelcipkins Sep 10, 2019
8631895
Merge branch 'tob-6255'
rachelcipkins Sep 10, 2019
b63290a
Started adding tests for release and expiration caveats.
rachelcipkins Sep 11, 2019
8ffb416
Started adding tests for release and expiration additions to the Crea…
rachelcipkins Sep 11, 2019
683448b
Changed wording on error messages added check to see if scope is user.
rachelcipkins Sep 11, 2019
b140178
Fixed logic error and typo.
rachelcipkins Sep 11, 2019
7b3bd1e
Changed release to releases.
rachelcipkins Sep 12, 2019
ad8f16c
Fixed errors in existing tests.
rachelcipkins Sep 12, 2019
77183f7
Added all_projects attribute to default_response.
rachelcipkins Sep 12, 2019
f9d2fb5
Revert "Added all_projects attribute to default_response."
rachelcipkins Sep 12, 2019
503d003
Added all_projects attribute to default_response.
rachelcipkins Sep 12, 2019
7fe87bd
Changed release to releases.
rachelcipkins Sep 12, 2019
4b4e45e
Removed unused function.
rachelcipkins Sep 12, 2019
879600e
Removed project_names.
rachelcipkins Sep 12, 2019
51b7642
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 12, 2019
1fb7db2
Added tests for full coverage.
rachelcipkins Sep 13, 2019
dd3ef4b
Changed format of validated_scope.
rachelcipkins Sep 13, 2019
9357cd4
Updated to match new format.
rachelcipkins Sep 13, 2019
117a3af
Added expiration to user scope.
rachelcipkins Sep 17, 2019
0d09209
Added tests for full coverage.
rachelcipkins Sep 17, 2019
1dfe594
Grammar / formatting fixes.
rachelcipkins Sep 17, 2019
b372344
Added/modified tests for full coverage.
rachelcipkins Sep 17, 2019
f130d8e
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 17, 2019
dbf9054
Removed notes.
rachelcipkins Sep 17, 2019
2355ff7
Updated to match new format.
rachelcipkins Sep 17, 2019
e23fc0f
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 17, 2019
9474015
Translation
rachelcipkins Sep 17, 2019
b9d2b0d
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 17, 2019
5117373
Merge branch 'master' into tob-new-caveats
rachelcipkins Sep 17, 2019
6b2b080
Hid release field when user scope selected.
rachelcipkins Sep 17, 2019
4c8e961
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 17, 2019
3a7941f
Merge branch 'tob-new-caveats' of github.com:trailofbits/warehouse in…
rachelcipkins Sep 17, 2019
9a46d0e
Black reformatting.
rachelcipkins Sep 18, 2019
2acb0e1
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 18, 2019
b5d6f57
Removed project_names / changed project_names test to all_projects.
rachelcipkins Sep 18, 2019
8fd501a
Parsed token_scope to just grab name of project for project-name field.
rachelcipkins Sep 18, 2019
88d19bc
Removed project_names.
rachelcipkins Sep 18, 2019
98cf8e6
Updated to use all_projects instead of project_names.
rachelcipkins Sep 18, 2019
a796938
Removed unused variables / packages.
rachelcipkins Sep 18, 2019
3b1bc04
Formatting fixes.
rachelcipkins Sep 18, 2019
a347b3e
Merge remote-tracking branch 'upstream/master' into tob-6255
rachelcipkins Sep 18, 2019
e8aeeaf
Formatting fixes.
rachelcipkins Sep 19, 2019
5a82f8f
Updated to handle previously created API token.
rachelcipkins Sep 19, 2019
f369279
Merge branch 'tob-6255' into tob-new-caveats
rachelcipkins Sep 19, 2019
fd5a530
Resolved merge conflict.
rachelcipkins Sep 19, 2019
e245102
Formatting fixes.
rachelcipkins Sep 19, 2019
8d2e44a
Revert "Black reformatting."
rachelcipkins Sep 19, 2019
92e51cf
Refixed formatting.
rachelcipkins Sep 19, 2019
79738f6
Merge branch 'master' into tob-new-caveats
woodruffw Sep 19, 2019
989a1db
warehouse: Refactor new caveats into a V2 format
woodruffw Sep 20, 2019
94a3ac3
tests: Began updating caveats tests
woodruffw Sep 23, 2019
40773f6
tests: Update manage/forms
woodruffw Sep 23, 2019
d599011
warehouse: Fix event recording for projects
woodruffw Sep 23, 2019
7bee8e7
tests: Fix manage/views tests
woodruffw Sep 23, 2019
51effcb
warehouse: Fix timestamp, return verify result
woodruffw Sep 23, 2019
6fa808d
tests: Update macaroon caveats tests
woodruffw Sep 23, 2019
5b504e5
tests: Fill in caveats, manage/forms tests
woodruffw Sep 23, 2019
ce96048
Merge branch 'master' into tob-new-caveats
woodruffw Sep 23, 2019
09f6469
Merge branch 'master' into tob-new-caveats
woodruffw Sep 23, 2019
4a0eb02
warehouse, test: Fix wrong key for version
woodruffw Sep 23, 2019
8a08fc2
Merge branch 'master' into tob-new-caveats
woodruffw Sep 24, 2019
8d3e66e
Added functionality for cornice REST api for upload tokens.
rachelcipkins Sep 30, 2019
2f1b699
Moved api to legacy directory.
rachelcipkins Sep 30, 2019
42c2525
Added route for token API endpoint.
rachelcipkins Sep 30, 2019
82ea5f3
Added token API endpoint.
rachelcipkins Sep 30, 2019
fedec1f
Added token API endpoint route.
rachelcipkins Sep 30, 2019
f71ea8c
Changed scope to match V2 caveats.
rachelcipkins Sep 30, 2019
e135886
Formatting fixes.
rachelcipkins Sep 30, 2019
f65eb3c
Started API endpoint for package uploads.
rachelcipkins Oct 10, 2019
f0a4f6a
Added test for invalid master token.
rachelcipkins Oct 10, 2019
44ca111
Removed notes.
rachelcipkins Oct 10, 2019
734c175
Removed unnecessary imports.
rachelcipkins Oct 15, 2019
aa2fdb9
Added one time use caveat.
rachelcipkins Oct 22, 2019
d9a698b
Added tests for one time use caveat.
rachelcipkins Oct 22, 2019
a00ed39
Formatting fixes.
rachelcipkins Oct 22, 2019
d9edc22
Added files to ignore.
rachelcipkins Oct 28, 2019
0c991b4
Removed unused variable.
rachelcipkins Oct 28, 2019
553065e
Merge branch 'master' into tob-one-time-token
woodruffw Nov 18, 2019
ee2a881
tests, warehouse: flake8 fixes
woodruffw Nov 18, 2019
d184a2e
tests/unit: Blacken
woodruffw Nov 18, 2019
4f5aaa9
tests, warehouse: isort fixes
woodruffw Nov 18, 2019
b7d299b
Merge branch 'master' into tob-one-time-token
woodruffw Nov 26, 2019
312f2e5
warehouse: Refactor token creation endpoint
woodruffw Dec 4, 2019
280144e
tests: Update macaroon caveat tests
woodruffw Dec 4, 2019
6769844
warehouse/routes: Auto-format
woodruffw Dec 4, 2019
8fbb669
tests/unit: Begin rewriting tests
woodruffw Dec 4, 2019
7865c10
tests/api: Add more token creation tests
woodruffw Dec 4, 2019
634e807
tests: Update management form strings
woodruffw Dec 5, 2019
e262de7
tests: Remove one-time-token tests
woodruffw Dec 5, 2019
e24fe65
tests: Remove unused import
woodruffw Dec 5, 2019
7f33a34
warehouse/api: Fix import orders
woodruffw Dec 5, 2019
66bd850
Merge branch 'master' into tob-one-time-token
woodruffw Dec 5, 2019
37051e9
warehouse, tests: Re-add one-time tokens
woodruffw Dec 6, 2019
87ca35a
warehouse/macaroons: Remove unused import
woodruffw Dec 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ node_modules/
dev/example.sql
dev/prod.sql
dev/prod.sql.xz
dev/notdatadog.py
dev/smtp.py
docs/conf.py
./data/

warehouse/.commit
Expand Down
49 changes: 48 additions & 1 deletion tests/unit/legacy/api/test_pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@
import pretend
import pytest

from pyramid.httpexceptions import HTTPBadRequest, HTTPMovedPermanently, HTTPNotFound
from pyramid.httpexceptions import (
HTTPBadRequest,
HTTPMovedPermanently,
HTTPNotFound,
HTTPUnauthorized,
)

from warehouse.legacy.api import pypi
from warehouse.macaroons.interfaces import IMacaroonService

from ....common.db.accounts import UserFactory
from ....common.db.classifiers import ClassifierFactory


Expand Down Expand Up @@ -209,3 +216,43 @@ def test_display_no_name(self, db_request):

with pytest.raises(HTTPNotFound):
pypi.display(db_request)


class TestToken:
@pytest.mark.parametrize(("project_name", "version"), [("foo", "1.0")])
def test_token_creation(self, db_request, macaroon_service, project_name, version):
user = UserFactory.create()
master_key, macaroon = macaroon_service.create_macaroon(
"fake location",
user.id,
"fake description",
{"version": 2, "permissions": "user"},
)
request = pretend.stub(
user=user,
domain="fake location",
find_service=lambda interface, **kw: {IMacaroonService: macaroon_service}[
interface
],
master_key=master_key,
project_name=project_name,
version=version,
description="fake description!",
)
assert isinstance(pypi.create_token(request), dict)

def test_invalid_master_token(self, macaroon_service):
user = UserFactory.create()
request = pretend.stub(
user=user,
domain="fake location",
find_service=lambda interface, **kw: {IMacaroonService: macaroon_service}[
interface
],
master_key="a fake key",
project_name="foo",
version="1.0",
description="fake description!",
)
with pytest.raises(HTTPUnauthorized):
pypi.create_token(request)
226 changes: 203 additions & 23 deletions tests/unit/macaroons/test_caveats.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import json
from datetime import datetime, timezone

import pretend
import pymacaroons
import pytest

from pymacaroons.exceptions import MacaroonInvalidSignatureException

from warehouse.macaroons.caveats import Caveat, InvalidMacaroon, V1Caveat, Verifier
from warehouse.macaroons.caveats import (
Caveat,
InvalidMacaroon,
TopLevelCaveat,
V1Caveat,
V2Caveat,
Verifier,
)

from ...common.db.packaging import ProjectFactory
from ...common.db.packaging import ProjectFactory, ReleaseFactory


class TestCaveat:
Expand All @@ -36,43 +44,163 @@ def test_creation(self):

class TestV1Caveat:
@pytest.mark.parametrize(
["predicate", "result"],
["predicate", "valid"],
[
("invalid json", False),
("", False),
("{}", False),
('{"version": 1, "permissions": "user"}', True),
('{"version": 1}', False),
('{"version": 2, "permissions": "user"}', True),
('{"version": 2}', False),
('{"permissions": null, "version": 1}', False),
('{"version": 3}', False),
],
)
def test_verify_invalid_predicates(self, predicate, result):
def test_verify_toplevel_caveat(self, monkeypatch, predicate, valid):
verifier = pretend.stub()
caveat = TopLevelCaveat(verifier)

if not valid:
with pytest.raises(InvalidMacaroon):
caveat(predicate)
else:
assert caveat(predicate)

@pytest.mark.parametrize(
"predicate", [{}, {"permissions": None}, {"permissions": {"projects": None}}]
)
def test_verify_invalid_v1_predicates(self, predicate):
verifier = pretend.stub()
caveat = V1Caveat(verifier)

with pytest.raises(InvalidMacaroon):
caveat(predicate)

def test_verify_valid_predicate(self):
verifier = pretend.stub()
@pytest.mark.parametrize(
"predicate",
[
{"version": 1, "permissions": {"projects": ["foobar"]}},
{"version": 1, "permissions": "user"},
],
)
def test_verify_valid_v1_predicates(self, db_request, predicate):
project = ProjectFactory.create(name="foobar")
verifier = pretend.stub(context=project)
caveat = V1Caveat(verifier)
predicate = '{"permissions": "user", "version": 1}'

assert caveat(predicate) is True
caveat(predicate)

def test_verify_project_invalid_context(self):
@pytest.mark.parametrize(
"predicate",
[
{"version": 1, "permissions": {"projects": ["notfoobar"]}},
{"version": 2, "permissions": {"projects": [{"name": "notfoobar"}]}},
],
)
def test_verify_project_invalid_context(self, predicate):
verifier = pretend.stub(context=pretend.stub())
caveat = V1Caveat(verifier)

predicate = {"version": 1, "permissions": {"projects": ["notfoobar"]}}
if predicate["version"] == 1:
caveat = V1Caveat(verifier)
else:
caveat = V2Caveat(verifier)

with pytest.raises(InvalidMacaroon):
caveat(json.dumps(predicate))
caveat(predicate)

@pytest.mark.parametrize(
["predicate", "valid"],
[
({"version": 2, "expiration": 0, "permissions": "user"}, False),
(
{
"version": 2,
"expiration": int(datetime.now(tz=timezone.utc).timestamp()) + 3600,
"permissions": "user",
},
True,
),
],
)
def test_verify_v2_caveat_expiration(self, predicate, valid):
verifier = pretend.stub()
caveat = V2Caveat(verifier)

if not valid:
with pytest.raises(InvalidMacaroon):
caveat(predicate)
else:
assert caveat(predicate)

@pytest.mark.parametrize(
["predicate", "valid"],
[
(
{
"version": 2,
"permissions": {"projects": [{"name": "foo", "version": "1.0.0"}]},
},
False,
),
(
{
"version": 2,
"permissions": {"projects": [{"name": "foo", "version": "1.0.1"}]},
},
True,
),
],
)
def test_verify_v2_caveat_release(self, db_request, predicate, valid):
project = ProjectFactory.create(name="foo")
ReleaseFactory.create(project=project, version="1.0.0")

verifier = pretend.stub(context=project)
caveat = V2Caveat(verifier)

if not valid:
with pytest.raises(InvalidMacaroon):
caveat(predicate)
else:
assert caveat(predicate)

@pytest.mark.parametrize(
["predicate", "valid"],
[
({"version": 2, "permissions": {"projects": [{"name": "foo"}]}}, False),
({"version": 2, "permissions": {}}, False),
({"version": 2, "permissions": {"projects": [{"name": "bar"}]}}, True),
],
)
def test_verify_v2_caveat_project(self, db_request, predicate, valid):
project = ProjectFactory.create(name="bar")
verifier = pretend.stub(context=project)
caveat = V2Caveat(verifier)

def test_verify_project_invalid_project_name(self, db_request):
if not valid:
with pytest.raises(InvalidMacaroon):
caveat(predicate)
else:
assert caveat(predicate)

@pytest.mark.parametrize(
"predicate",
[
{"version": 1, "permissions": {"projects": ["notfoobar"]}},
{"version": 2, "permissions": {"projects": [{"name": "notfoobar"}]}},
],
)
def test_verify_project_invalid_project_name(self, db_request, predicate):
project = ProjectFactory.create(name="foobar")
verifier = pretend.stub(context=project)
caveat = V1Caveat(verifier)

predicate = {"version": 1, "permissions": {"projects": ["notfoobar"]}}
if predicate["version"] == 1:
caveat = V1Caveat(verifier)
else:
caveat = V2Caveat(verifier)

with pytest.raises(InvalidMacaroon):
caveat(json.dumps(predicate))
caveat(predicate)

def test_verify_project_no_projects_object(self, db_request):
project = ProjectFactory.create(name="foobar")
Expand All @@ -84,15 +212,42 @@ def test_verify_project_no_projects_object(self, db_request):
"permissions": {"somethingthatisntprojects": ["blah"]},
}
with pytest.raises(InvalidMacaroon):
caveat(json.dumps(predicate))
caveat(predicate)

def test_verify_project(self, db_request):
@pytest.mark.parametrize(
"predicate",
[
{"version": 1, "permissions": {"projects": ["foobar"]}},
{"version": 2, "permissions": {"projects": [{"name": "foobar"}]}},
],
)
def test_verify_project(self, db_request, predicate):
project = ProjectFactory.create(name="foobar")
ReleaseFactory.create(project=project)
verifier = pretend.stub(context=project)
caveat = V1Caveat(verifier)

predicate = {"version": 1, "permissions": {"projects": ["foobar"]}}
assert caveat(json.dumps(predicate)) is True
if predicate["version"] == 1:
caveat = V1Caveat(verifier)
else:
caveat = V2Caveat(verifier)

assert caveat(predicate) is True

@pytest.mark.parametrize(
["predicate", "valid"],
[
('{"version": 2, "permissions": "user"}', True),
('{"version": 2, "permissions": "user", "used": true}', False),
],
)
def test_verify_one_time_token_caveat(self, predicate, valid):
verifier = pretend.stub()
caveat = TopLevelCaveat(verifier)
if not valid:
with pytest.raises(InvalidMacaroon):
caveat(predicate)
else:
assert caveat(predicate)


class TestVerifier:
Expand Down Expand Up @@ -123,3 +278,28 @@ def test_verify(self, monkeypatch):
with pytest.raises(InvalidMacaroon):
verifier.verify(key)
assert verify.calls == [pretend.call(macaroon, key)]

@pytest.mark.parametrize(
"predicate",
[
{"version": 2, "permissions": "user"},
{"version": 2, "permissions": {"projects": [{"name": "bar"}]}},
{"version": 2, "permissions": "user", "used": "true"},
],
)
def test_verify_one_time_token(self, macaroon_service, predicate):
project = ProjectFactory.create(name="bar")
macaroon_obj = pymacaroons.Macaroon(
location="fake location",
identifier="identifier",
key="key",
version=pymacaroons.MACAROON_V2,
)
macaroon = macaroon_obj
context = project
principals = pretend.stub()
permission = predicate
key = "key"
verifier = Verifier(macaroon, context, principals, permission)

assert verifier.verify(key)
Loading