Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
[#227] Implement feature, update python to 3.10
Browse files Browse the repository at this point in the history
  • Loading branch information
gimppa committed Jun 21, 2023
1 parent a7d28ae commit 08e8fa7
Show file tree
Hide file tree
Showing 18 changed files with 88 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
max-parallel: 4
matrix:
os: [ubuntu-latest]
python-version: [3.8]
python-version: [3.10]

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/int.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
max-parallel: 4
matrix:
os: [ubuntu-latest]
python-version: [3.8]
python-version: [3.10]

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
max-parallel: 4
matrix:
os: [ubuntu-latest]
python-version: [3.8]
python-version: [3.10]

runs-on: ${{ matrix.os }}

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
max-parallel: 4
matrix:
os: [ubuntu-latest]
python-version: [3.8]
python-version: [3.10]

runs-on: ${{ matrix.os }}

Expand All @@ -29,7 +29,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions coverage
- name: Run unit tests for python 3.8
- name: Run unit tests for python 3.10
run: |
tox -e unit_tests
coverage lcov -o lcov.info
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-alpine3.15 as BUILD
FROM python:3.10.12-alpine3.18 as BUILD

RUN apk add --update \
&& apk add --no-cache build-base curl-dev linux-headers bash git musl-dev\
Expand All @@ -18,7 +18,7 @@ COPY setup.py /root/beacon/setup.py
COPY beacon_api /root/beacon/beacon_api
RUN pip install /root/beacon

FROM python:3.8-alpine3.15
FROM python:3.10.12-alpine3.18

RUN apk add --no-cache --update bash

Expand All @@ -29,7 +29,7 @@ LABEL org.label-schema.vcs-url="https://github.com/CSCFI/beacon-python"
RUN apk add --update \
&& apk add --no-cache curl bzip2 xz

COPY --from=BUILD usr/local/lib/python3.8/ usr/local/lib/python3.8/
COPY --from=BUILD usr/local/lib/python3.10/ usr/local/lib/python3.10/

COPY --from=BUILD /usr/local/bin/gunicorn /usr/local/bin/

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Documentation: https://beacon-python.readthedocs.io
### Quick start

`beacon-python` Web Server requires:
* Python 3.8+;
* Python 3.10+;
* running DB [PostgreSQL Server](https://www.postgresql.org/) 9.6+ (recommended 13).

```shell
Expand Down
4 changes: 2 additions & 2 deletions beacon_api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def main():


if __name__ == "__main__":
if sys.version_info < (3, 8):
LOG.error("beacon-python requires python 3.8")
if sys.version_info < (3, 10):
LOG.error("beacon-python requires python 3.10")
sys.exit(1)
main()
3 changes: 2 additions & 1 deletion beacon_api/conf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,14 @@ def parse_oauth2_config_file(path: str) -> Any:
"""Parse configuration file."""
config = ConfigParser()
config.read(path)
config_vars: Dict[str, Union[str, bool, None]] = {
config_vars: Dict[str, Union[str, bool, None, List[str]]] = {
"server": config.get("oauth2", "server"),
"issuers": config.get("oauth2", "issuers"),
"userinfo": config.get("oauth2", "userinfo"),
"audience": config.get("oauth2", "audience") or None,
"verify_aud": bool(strtobool(config.get("oauth2", "verify_aud"))),
"bona_fide_value": config.get("oauth2", "bona_fide_value"),
"trusted_jkus": config.get("oauth2", "trusted_jkus", fallback="").split(","),
}
return convert(config_vars)

Expand Down
4 changes: 4 additions & 0 deletions beacon_api/conf/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,7 @@ audience=
# If your service is not part of any network or AAI, but you still want to use tokens
# produced by other AAI parties, set this value to False to skip the audience validation step
verify_aud=False

# Comma separated list of trusted JKUs
# JTW with an untrusted JKU will be denied access
trusted_jkus=http://test.csc.fi/jwkboofar
8 changes: 7 additions & 1 deletion beacon_api/permissions/ga4gh.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,19 @@ async def get_ga4gh_permissions(token: str) -> Tuple[set, bool]:

# Get encoded passports (assorted JWTs) from /userinfo
encoded_passports = await retrieve_user_data(token)

# Pre-process the assorted passports (JWTs) for dataset permissions and bona fide status parsing
if encoded_passports:
# Decode the passports and check their type
for encoded_passport in encoded_passports:
# Decode passport
header, payload = await decode_passport(encoded_passport)
# If trusted_jkus variable is set, only allow passports with a trusted JKU
if not OAUTH2_CONFIG.trusted_jkus == [""]:
# Skip passports with untrusted JKUs
passport_jku = header.get("jku")
if passport_jku not in OAUTH2_CONFIG.trusted_jkus:
LOG.debug("Untrusted JKU.")
continue
# Sort passports that carry dataset permissions
pass_type = payload.get("ga4gh_visa_v1", {}).get("type")
if pass_type == "ControlledAccessGrants": # nosec
Expand Down
2 changes: 1 addition & 1 deletion beacon_api/utils/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
# Keeping it simple with the logging formatting

formatting = "[%(asctime)s][%(name)s][%(process)d %(processName)s][%(levelname)-8s] (L:%(lineno)s) %(module)s | %(funcName)s: %(message)s"
logging.basicConfig(level=logging.INFO, format=formatting)
logging.basicConfig(level=logging.DEBUG, format=formatting)

LOG = logging.getLogger("beacon")
2 changes: 1 addition & 1 deletion docs/instructions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Instructions

.. note:: In order to run ``beacon-python`` Web Server requirements are as specified below:

* Python 3.8+;
* Python 3.10+;
* running DB `PostgreSQL Server <https://www.postgresql.org/>`_ 9.6+ (recommended 13).

.. _env-setup:
Expand Down
2 changes: 1 addition & 1 deletion readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build:
image: latest
requirements_file: docs/docs.txt
python:
version: 3.8
version: 3.10
use_system_site_packages: true
setup_py_install: true
extra_requirements:
Expand Down
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
"Topic :: Scientific/Engineering :: Bio-Informatics",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.10",
],
install_requires=[
"asyncpg==0.27.0",
Expand Down
4 changes: 4 additions & 0 deletions tests/test.ini
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,7 @@ audience=
# If your service is not part of any network or AAI, but you still want to use tokens
# produced by other AAI parties, set this value to False to skip the audience validation step
verify_aud=False

# Comma separated list of trusted JKUs
# JTW with an untrusted JKU will be denied access
trusted_jkus=http://test.csc.fi/jwk
2 changes: 1 addition & 1 deletion tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json
from authlib.jose import jwt
import os
from test.support import EnvironmentVarGuard
from test.support.os_helper import EnvironmentVarGuard
from aiocache import caches


Expand Down
54 changes: 53 additions & 1 deletion tests/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import unittest
import aiohttp
import unittest.mock
from beacon_api.utils.db_load import parse_arguments, init_beacon_db, main
from beacon_api.conf.config import init_db_pool
from beacon_api.api.query import access_resolution
Expand All @@ -8,7 +9,8 @@
from beacon_api.permissions.ga4gh import check_ga4gh_token, decode_passport, get_ga4gh_permissions
from .test_app import PARAMS, generate_token
from testfixtures import TempDirectory
from test.support import EnvironmentVarGuard
from test.support.os_helper import EnvironmentVarGuard
from beacon_api.conf import OAUTH2_CONFIG


def mock_token(bona_fide, permissions, auth):
Expand Down Expand Up @@ -70,6 +72,11 @@ async def load_datafile(self, vcf, datafile, datasetId, n=1000, min_ac=1):
return ["datasetId", "variants"]


async def mock_get_ga4gh_controlled(input):
"""Mock retrieve dataset permissions."""
return input


class TestBasicFunctions(unittest.IsolatedAsyncioTestCase):
"""Test supporting functions."""

Expand Down Expand Up @@ -482,5 +489,50 @@ async def test_get_ga4gh_permissions(self, m_userinfo, m_decode, m_controlled, m
self.assertEqual(bona_fide_status, True)


class TestCaseCheckJku(unittest.IsolatedAsyncioTestCase):
"""Test case."""

@unittest.mock.patch("beacon_api.permissions.ga4gh.get_ga4gh_bona_fide")
@unittest.mock.patch("beacon_api.permissions.ga4gh.get_ga4gh_controlled", side_effect=mock_get_ga4gh_controlled)
@unittest.mock.patch("beacon_api.permissions.ga4gh.decode_passport")
@unittest.mock.patch("beacon_api.permissions.ga4gh.retrieve_user_data")
async def test_jku_check(self, m_userinfo, m_decode, m_controller, m_bonafide):
"""Test trusted and untrusted jku."""
# Test: trusted jku
m_userinfo.return_value = [""]
header = {"jku": "http://test.csc.fi/jwk"}
payload = {"ga4gh_visa_v1": {"type": "ControlledAccessGrants"}}
m_decode.return_value = header, payload
m_bonafide.return_value = False
dataset_permissions, bona_fide_status = await get_ga4gh_permissions({})
self.assertEqual(dataset_permissions, [("", header)])
self.assertEqual(bona_fide_status, False)
# Test: untrusted jku
m_userinfo.return_value = [""]
header = {"jku": "untrusted_jku"}
payload = {"ga4gh_visa_v1": {"type": "ControlledAccessGrants"}}
m_decode.return_value = header, payload
m_bonafide.return_value = False
dataset_permissions, bona_fide_status = await get_ga4gh_permissions({})
self.assertEqual(dataset_permissions, [])
self.assertEqual(bona_fide_status, False)

@unittest.mock.patch("beacon_api.permissions.ga4gh.OAUTH2_CONFIG", new=OAUTH2_CONFIG._replace(trusted_jkus=[""]))
@unittest.mock.patch("beacon_api.permissions.ga4gh.get_ga4gh_bona_fide")
@unittest.mock.patch("beacon_api.permissions.ga4gh.get_ga4gh_controlled", side_effect=mock_get_ga4gh_controlled)
@unittest.mock.patch("beacon_api.permissions.ga4gh.decode_passport")
@unittest.mock.patch("beacon_api.permissions.ga4gh.retrieve_user_data")
async def test_jku_check_not_active(self, m_userinfo, m_decode, m_controller, m_bonafide):
"""Test if jku check is skipped when trusted_jkus config var is not set."""
m_userinfo.return_value = [""]
header = {"jku": "untrusted_jku"}
payload = {"ga4gh_visa_v1": {"type": "ControlledAccessGrants"}}
m_decode.return_value = header, payload
m_bonafide.return_value = False
dataset_permissions, bona_fide_status = await get_ga4gh_permissions({})
self.assertEqual(dataset_permissions, [("", header)])
self.assertEqual(bona_fide_status, False)


if __name__ == "__main__":
unittest.main()
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ deps =
.[test]
-rrequirements.txt
# Stop after first failure
commands = py.test -x --cov=beacon_api tests/ --cov-fail-under=80
commands = py.test -x --cov=beacon_api tests/ --cov-fail-under=80 --cov-report html

[gh-actions]
python =
3.8: flake8, unit_tests, docs, bandit, mypy
3.10: flake8, unit_tests, docs, bandit, mypy

0 comments on commit 08e8fa7

Please sign in to comment.