Skip to content

BioConnect Authorization Template: Django Application:

The template include:

  • django application with endpoints and users
  • added authorization

Create Django Base Application

Create a Django base application, using peotry to manage the dependency

Create a new Poetry project

mkdir bioconnect-api-template && cd bioconnect-api-template
poetry init

Add Django and init Django project

poetry add django
poetry run django-admin startproject bioconnect_api_template .
If you need to have the requirements.txt file with all the dependencies, you can run
poetry export -f requirements.txt --output requirements.txt

Run Django

python manage.py runserver
open http://localhost:8000

Create API endpoints

In order to create API endpoints, start to add a "sample" app into the project

python manage.py startapp sample

edit "models.py" in "sample" directory

from django.db import models

class Sample(models.Model):
    """
    A sample 
    """
    name = models.CharField(max_length=256, null=False, blank=False)
    description = models.CharField(max_length=5000, null=False, blank=False)

    class Meta:
        verbose_name = 'Sample'
        verbose_name_plural = 'Samples'

edit "serializers.py" in "sample" directory

from rest_framework import serializers
from . import models

class SampleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Sample
        fields = '__all__'

edit "views.py" in "sample" directory

from rest_framework import viewsets
from rest_framework import permissions
from . import models, serializers

class SampleViewSet(viewsets.ModelViewSet):
    queryset = models.Sample.objects.all()
    serializer_class = serializers.SampleSerializer
    permission_classes = [permissions.IsAuthenticated]

create a new file "urls.py" in "sample" directory

from django.urls import path
from . import views
from rest_framework import routers

router = routers.SimpleRouter()
router.register(r"sample", views.SampleViewSet)
urlpatterns = router.urls

edit root "settings.py", add 'sample.apps.SampleConfig' to the "INSTALLED_APPS"

INSTALLED_APPS = [
    'sample.apps.SampleConfig',
    'django.contrib.admin',
    ...
]

edit root "urls.py", add new entry in URL

urlpatterns = [
    path('sample/', include('sample.urls')),
    ...
]

save the model into the database

python manage.py makemigrations sample
python manage.py migrate

Add Swagger UI

add swagger UI library

poetry add django-rest-swagger
poetry add drf-yasg

edit root "urls.py", add swagger libray import and code

from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework import permissions

schema_view = get_schema_view(
    openapi.Info(
        title="BioConnect Template APIs",
        default_version='v1',
        description="API Specificiation for JAX BioConnect Template",
        terms_of_service="https://www.google.com/policies/terms/",
        contact=openapi.Contact(email="contact@jax.org"),
        license=openapi.License(name="BSD License"),
    ),
    public=True,
    permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    re_path(r'^swagger(?P<format>\.json|\.yaml)$',
            schema_view.without_ui(cache_timeout=0), name='schema-json'),

    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0),
         name='schema-swagger-ui'),
    ......
]
open http://localhost:8000/swagger to see the API endpoints

BioConnect Authorization

Library installation

The BioConnect authorization library is available from PyPI, the Python packaging index.

https://test.pypi.org/project/bioconnect-lib

Installation can be done in the usual ways by adding the repository to your Poetry pyproject.toml file, or to requirements.py for pip. With pip from the command line do:

# add dependency
apache-ranger = "^0.0.5"
environs = "^9.5.0"
elasticsearch7 = "^7.17.1"
python-logstash = "^0.4.6"
azure-servicebus = "^7.6.1"
marshmallow = "^3.15.0"

pip install --index-url https://test.pypi.org/simple/ bioconnect-lib

New Permission Class

Add a new file "bioconnect_permission.py" to define a class "BioConnectPermisison".
The "BioConnectPermisison" is a subclass of "permissions.BasePermission" in the rest_framework. It overwrites the two methods to use Apache Ranger for authorization.

This is the class for all the views.

from rest_framework import permissions
from bioconnect_lib.ranger.authorizer_api import ranger_is_access_allowed_api
from bioconnect_lib.ranger.request_api import AuthorizerRequestAPI
import logging
logger = logging.getLogger(__name__)

class BioConnectPermisison(permissions.BasePermission):
    RANGER_SERVICE_NAME = 'bioconnect-api-template'

    def has_permission(self, request, view):

        if not request.user.is_authenticated:
            return False

        auth_request = AuthorizerRequestAPI(
            user_id = request.user.username,
            service_name = BioConnectPermisison.RANGER_SERVICE_NAME,
            action = request.method,
            host = request._request._current_scheme_host,
            path = request.path,
        )

        try:
            response = ranger_is_access_allowed_api(auth_request)
            return response.is_allowed
            logger.info(f'response: {response}')
        except Exception as e:
            logger.error("Failed to authorize", exc_info=True)

    def has_object_permission(self, request, view, obj):
        return True

Add Permission View

For the views to be protected, add import and the class to permission_classes

from rest_framework import viewsets
from rest_framework import permissions
from . import models, serializers
from bioconnect_api_template.bioconnect_permission import BioConnectPermisison

class SampleViewSet(viewsets.ModelViewSet):
    queryset = models.Sample.objects.all()
    serializer_class = serializers.SampleSerializer
    permission_classes = [BioConnectPermisison]

Set Up Django Users

Create admin user by run

python manage.py createsuperuser

Start the app, and login to the admin console: http://localhost:8000/admin

Create two more users with user_id "guest", and "editor". Remember the password.
Only user_id and password matters, and all other fields can be ignored. The user_id needs to match the exact user_id in the Ranger. The Ranger only does the authorization based on the user_id.

Three users in the system:

  • adimin
  • editor
  • viewer

Config in Apache Ranger

Add service

To use Apache Ranger for authorization, a new instance of BIOCONNECT-SERVICE needs to be created, and name it as "bioconnect-api-template", which should be the same name as in Django for the permission class. Ranger Service

Add policy

To add, click on the service name "bioconnect-api-template" Ranger Policy

The policy detail is. Ranger Policy

  • admin: can call "get", "post", "patch", "put", "delete"
  • editor: can call "get", "post", "patch", "put"
  • guest: only can call "get" end point

For detail steps, refer to BioConnect Authorization

Test Authorization

Start the app, and open swagger UI in the browser: http://localhost:8000/swagger

Swagger

Test Get Sample

Click on "GET" "/sample/" to expand, click on "Try it out" button, and then "Execute" button. Error:

{
  "detail": "Authentication credentials were not provided."
}
Swagger

Add User Info

Click on "Authroize" button

Swagger

Test Post Sample

Now try "POST", "/sample/" with guest account, error will occur Swagger

Check Audit Log

Check the Ranger audit log, "Denied" entry: Swagger