Skip to content

Commit

Permalink
remove the pinned starlette version
Browse files Browse the repository at this point in the history
It removes the pinned starlette dependency version

This pinned version was applied as a workaround for issue repository-service-tuf#183

The startelle version is updated to the latest version, which fixes a
security issue GHSA-74m5-2c7w-9w3x

The solution requires to install the new `httpx` development
dependency to support the unit tests using the FastAPI TestClient as
described in this link: https://fastapi.tiangolo.com/tutorial/testing/

A workaround needs to be applied to the tests which uses `DELETE`
method.

Signed-off-by: Kairo de Araujo <kdearaujo@vmware.com>
  • Loading branch information
Kairo de Araujo committed Feb 23, 2023
1 parent 0a2d7de commit c536857
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 107 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Expand Up @@ -14,7 +14,6 @@ python-jose = "*"
sqlalchemy = "*"
redis = "*"
bcrypt = "*"
starlette = "==0.20.4"

[dev-packages]
black = "*"
Expand All @@ -40,6 +39,7 @@ mistune = "==0.8.4"
myst-parser = "*"
pre-commit = "*"
bandit = "*"
httpx = "*"

[requires]
python_version = "3.10"
202 changes: 126 additions & 76 deletions Pipfile.lock

Large diffs are not rendered by default.

25 changes: 14 additions & 11 deletions requirements-dev.txt
@@ -1,5 +1,6 @@
-i https://pypi.org/simple
alabaster==0.7.13 ; python_version >= '3.6'
anyio==3.6.2 ; python_full_version >= '3.6.2'
attrs==22.2.0 ; python_version >= '3.6'
babel==2.11.0 ; python_version >= '3.6'
bandit==1.7.4
Expand All @@ -12,7 +13,7 @@ chardet==5.1.0 ; python_version >= '3.7'
charset-normalizer==3.0.1 ; python_full_version >= '3.6.0'
click==8.1.3 ; python_version >= '3.7'
colorama==0.4.6 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'
coverage==7.1.0
coverage==7.2.0
cryptography==39.0.1
distlib==0.3.6
docutils==0.18.1 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
Expand All @@ -21,6 +22,9 @@ filelock==3.9.0 ; python_version >= '3.7'
flake8==6.0.0
gitdb==4.0.10 ; python_version >= '3.7'
gitpython==3.1.31 ; python_version >= '3.7'
h11==0.14.0 ; python_version >= '3.7'
httpcore==0.16.3 ; python_version >= '3.7'
httpx==0.23.3
identify==2.5.18 ; python_version >= '3.7'
idna==3.4 ; python_version >= '3.5'
imagesize==1.4.1 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
Expand All @@ -29,7 +33,7 @@ isort==5.12.0
jinja2==3.1.2 ; python_version >= '3.7'
jsonschema==4.17.3 ; python_version >= '3.7'
m2r==0.3.1
markdown-it-py==2.1.0 ; python_version >= '3.7'
markdown-it-py==2.2.0 ; python_version >= '3.7'
markupsafe==2.1.2 ; python_version >= '3.7'
mccabe==0.7.0 ; python_version >= '3.6'
mdit-py-plugins==0.3.4 ; python_version >= '3.7'
Expand All @@ -43,7 +47,7 @@ pathspec==0.11.0 ; python_version >= '3.7'
pbr==5.11.1 ; python_version >= '2.6'
platformdirs==3.0.0 ; python_version >= '3.7'
pluggy==1.0.0 ; python_version >= '3.6'
pre-commit==3.0.4
pre-commit==3.1.0
pretend==1.0.9
pycodestyle==2.10.0 ; python_version >= '3.6'
pycparser==2.21
Expand All @@ -55,9 +59,11 @@ pytest==7.2.1
pytz==2022.7.1
pyyaml==6.0 ; python_version >= '3.6'
requests==2.28.2 ; python_version >= '3.7' and python_version < '4'
setuptools==67.3.3 ; python_version >= '3.7'
rfc3986[idna2008]==1.5.0
setuptools==67.4.0 ; python_version >= '3.7'
six==1.16.0 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
smmap==5.0.0 ; python_version >= '3.6'
sniffio==1.3.0 ; python_version >= '3.7'
snowballstemmer==2.2.0
sphinx==5.3.0
sphinx-rtd-theme==1.2.0
Expand All @@ -73,13 +79,12 @@ sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
stevedore==5.0.0 ; python_version >= '3.8'
tomli==2.0.1 ; python_version < '3.11'
tox==4.4.5
tox==4.4.6
typing-extensions==4.5.0 ; python_version >= '3.7'
urllib3==1.26.14 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
virtualenv==20.19.0 ; python_version >= '3.7'
voluptuous==0.13.1
amqp==5.1.1 ; python_version >= '3.6'
anyio==3.6.2 ; python_full_version >= '3.6.2'
async-timeout==4.0.2 ; python_version >= '3.6'
bcrypt==4.0.1
billiard==3.6.4.0
Expand All @@ -90,20 +95,18 @@ click-repl==0.2.0
configobj==5.0.8
dynaconf==3.1.11
ecdsa==0.18.0 ; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
fastapi==0.86.0
fastapi==0.92.0
greenlet==2.0.2 ; platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))
h11==0.14.0 ; python_version >= '3.7'
kombu==5.2.4 ; python_version >= '3.7'
prompt-toolkit==3.0.36 ; python_full_version >= '3.6.2'
prompt-toolkit==3.0.37 ; python_full_version >= '3.7.0'
pyasn1==0.4.8
pydantic==1.10.5 ; python_version >= '3.7'
python-jose==3.3.0
python-multipart==0.0.5
redis==4.5.1
rsa==4.9 ; python_version >= '3.6' and python_version < '4'
sniffio==1.3.0 ; python_version >= '3.7'
sqlalchemy==2.0.4
starlette==0.20.4
starlette==0.25.0 ; python_version >= '3.7'
uvicorn==0.20.0
vine==5.0.0 ; python_version >= '3.6'
wcwidth==0.2.6
6 changes: 3 additions & 3 deletions requirements.txt
Expand Up @@ -12,12 +12,12 @@ click-repl==0.2.0
configobj==5.0.8
dynaconf==3.1.11
ecdsa==0.18.0 ; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
fastapi==0.86.0
fastapi==0.92.0
greenlet==2.0.2 ; platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))
h11==0.14.0 ; python_version >= '3.7'
idna==3.4 ; python_version >= '3.5'
kombu==5.2.4 ; python_version >= '3.7'
prompt-toolkit==3.0.36 ; python_full_version >= '3.6.2'
prompt-toolkit==3.0.37 ; python_full_version >= '3.7.0'
pyasn1==0.4.8
pydantic==1.10.5 ; python_version >= '3.7'
python-jose==3.3.0
Expand All @@ -28,7 +28,7 @@ rsa==4.9 ; python_version >= '3.6' and python_version < '4'
six==1.16.0 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
sniffio==1.3.0 ; python_version >= '3.7'
sqlalchemy==2.0.4
starlette==0.20.4
starlette==0.25.0 ; python_version >= '3.7'
typing-extensions==4.5.0 ; python_version >= '3.7'
uvicorn==0.20.0
vine==5.0.0 ; python_version >= '3.6'
Expand Down
13 changes: 5 additions & 8 deletions tests/unit/api/test_bootstrap.py
Expand Up @@ -12,7 +12,6 @@ class TestGetBoostrap:
def test_get_boostrap_available(
self, test_client, token_headers, monkeypatch
):

url = "/api/v1/bootstrap/"
mocked_check_metadata = pretend.call_recorder(lambda: False)
monkeypatch.setattr(
Expand All @@ -22,7 +21,7 @@ def test_get_boostrap_available(

response = test_client.get(url, headers=token_headers)
assert response.status_code == status.HTTP_200_OK
assert response.url == test_client.base_url + url
assert response.url == f"{test_client.base_url}{url}"
assert response.json() == {
"data": {"bootstrap": False},
"message": "System available for bootstrap.",
Expand All @@ -32,7 +31,6 @@ def test_get_boostrap_available(
def test_get_boostrap_not_available(
self, test_client, monkeypatch, token_headers
):

url = "/api/v1/bootstrap/"

mocked_check_metadata = pretend.call_recorder(lambda: True)
Expand All @@ -43,15 +41,14 @@ def test_get_boostrap_not_available(

response = test_client.get(url, headers=token_headers)
assert response.status_code == status.HTTP_200_OK
assert response.url == test_client.base_url + url
assert response.url == f"{test_client.base_url}{url}"
assert response.json() == {
"data": {"bootstrap": True},
"message": "System LOCKED for bootstrap.",
}
assert mocked_check_metadata.calls == [pretend.call()]

def test_get_boostrap_invalid_token(self, test_client, monkeypatch):

url = "/api/v1/bootstrap/"
mocked_check_metadata = pretend.call_recorder(lambda: False)
monkeypatch.setattr(
Expand Down Expand Up @@ -129,7 +126,7 @@ def test_post_bootstrap(self, test_client, monkeypatch, token_headers):
response = test_client.post(url, json=payload, headers=token_headers)

assert response.status_code == status.HTTP_202_ACCEPTED
assert response.url == test_client.base_url + url
assert response.url == f"{test_client.base_url}{url}"
assert response.json() == {
"message": "Bootstrap accepted.",
"data": {"task_id": "123"},
Expand All @@ -153,7 +150,7 @@ def test_post_bootstrap_already_bootstrap(
response = test_client.post(url, json=payload, headers=token_headers)

assert response.status_code == status.HTTP_200_OK
assert response.url == test_client.base_url + url
assert response.url == f"{test_client.base_url}{url}"
assert response.json() == {
"detail": {"error": "System already has a Metadata."}
}
Expand All @@ -164,7 +161,7 @@ def test_post_bootstrap_empty_payload(self, test_client, token_headers):
response = test_client.post(url, json={}, headers=token_headers)

assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
assert response.url == test_client.base_url + url
assert response.url == f"{test_client.base_url}{url}"
assert response.json() == {
"detail": [
{
Expand Down
36 changes: 30 additions & 6 deletions tests/unit/api/test_targets.py
Expand Up @@ -303,7 +303,11 @@ def test_delete(self, monkeypatch, test_client, token_headers):
"repository_service_tuf_api.targets.datetime", fake_datetime
)

response = test_client.delete(url, json=payload, headers=token_headers)
# https://github.com/tiangolo/fastapi/issues/5649
response = test_client.request(
"DELETE", url, json=payload, headers=token_headers
)

assert response.status_code == status.HTTP_202_ACCEPTED
assert response.json() == {
"data": {
Expand Down Expand Up @@ -359,7 +363,11 @@ def test_delete_publish_targets_false(
"repository_service_tuf_api.targets.datetime", fake_datetime
)

response = test_client.delete(url, json=payload, headers=token_headers)
# https://github.com/tiangolo/fastapi/issues/5649
response = test_client.request(
"DELETE", url, json=payload, headers=token_headers
)

assert response.status_code == status.HTTP_202_ACCEPTED
msg = (
"Remove Target(s) successfully submitted. "
Expand Down Expand Up @@ -397,7 +405,11 @@ def test_delete_without_bootstrap(
"repository_service_tuf_api.targets.is_bootstrap_done",
lambda: False,
)
response = test_client.delete(url, json=payload, headers=token_headers)
# https://github.com/tiangolo/fastapi/issues/5649
response = test_client.request(
"DELETE", url, json=payload, headers=token_headers
)

assert response.status_code == status.HTTP_200_OK
assert response.json() == {
"detail": {"error": "System has not a Repository Metadata"}
Expand All @@ -408,7 +420,11 @@ def test_delete_missing_required_field(self, test_client, token_headers):

payload = {"paths": ["file-v1.0.0_i683.tar.gz", "v0.4.1/file.tar.gz"]}

response = test_client.delete(url, json=payload, headers=token_headers)
# https://github.com/tiangolo/fastapi/issues/5649
response = test_client.request(
"DELETE", url, json=payload, headers=token_headers
)

assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY

def test_delete_unauthorized_invalid_token(self, test_client):
Expand All @@ -421,7 +437,11 @@ def test_delete_unauthorized_invalid_token(self, test_client):
"targets": ["file-v1.0.0_i683.tar.gz", "v0.4.1/file.tar.gz"]
}

response = test_client.delete(url, json=payload, headers=headers)
# https://github.com/tiangolo/fastapi/issues/5649
response = test_client.request(
"DELETE", url, json=payload, headers=headers
)

assert response.status_code == status.HTTP_401_UNAUTHORIZED
assert response.json() == {
"detail": {"error": "Failed to validate token"}
Expand All @@ -444,7 +464,11 @@ def test_post_forbidden_user_incorrect_scope_token(self, test_client):
"targets": ["file-v1.0.0_i683.tar.gz", "v0.4.1/file.tar.gz"]
}

response = test_client.delete(url, json=payload, headers=headers)
# https://github.com/tiangolo/fastapi/issues/5649
response = test_client.request(
"DELETE", url, json=payload, headers=headers
)

assert response.status_code == status.HTTP_403_FORBIDDEN
assert response.json() == {
"detail": {"error": "scope 'delete:targets' not allowed"}
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_app.py
Expand Up @@ -8,14 +8,14 @@
def test_root(test_client):
response = test_client.get("/")

assert response.url == test_client.base_url + "/"
assert response.url == f"{test_client.base_url}/"
assert response.status_code == status.HTTP_200_OK
assert "Repository Service for TUF API" in response.text


def test_default_notfound(test_client):
response = test_client.get("/invalid_url")

assert response.url == test_client.base_url + "/invalid_url"
assert response.url == f"{test_client.base_url}/invalid_url"
assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json() == {"detail": "Not Found"}

0 comments on commit c536857

Please sign in to comment.