Commit b2c2badc authored by Lukas Burgey's avatar Lukas Burgey

Lint a lot of code

parent b5b15984
from ... import models
import logging
import json
from urllib.request import Request, urlopen
from django.db.utils import OperationalError
from django.core.exceptions import ObjectDoesNotExist
from django.db import models as db_models
from oic.oic import Client
from oic.oic.message import RegistrationResponse
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from urllib.request import Request, urlopen
import json
from ... import models
import logging
logger = logging.getLogger(__name__)
LOGGER = logging.getLogger(__name__)
oidc_client = {}
OIDC_CLIENT = {}
class OIDCConfig(db_models.Model):
......@@ -30,21 +30,19 @@ class OIDCConfig(db_models.Model):
@property
def oidc_client(self):
global oidc_client
if self.id not in oidc_client:
if self.id not in OIDC_CLIENT:
new_oidc_client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
new_oidc_client.provider_config(self.issuer_uri)
new_oidc_client.store_registration_info(self.registration_response)
oidc_client[self.id] = new_oidc_client
return oidc_client[self.id]
OIDC_CLIENT[self.id] = new_oidc_client
return OIDC_CLIENT[self.id]
@property
def provider_info(self):
return self.oidc_client.provider_info
@property
def name(self):
return self.issuer_uri
def __str__(self):
return self.name
def get_auth_request(self, client, state):
args = {
......@@ -56,12 +54,10 @@ class OIDCConfig(db_models.Model):
}
auth_req = client.construct_AuthorizationRequest(
request_args=args)
request_args=args
)
return auth_req.request(client.authorization_endpoint)
def __str__(self):
return self.name
def default_idp():
return OIDCConfig.objects.filter(enabled=True).first()
......@@ -72,15 +68,17 @@ class OIDCTokenAuthBackend(object):
try:
idp_id = request.session['idp_id']
except OperationalError:
logger.error('OperationalError: Unable to get from session')
LOGGER.error('OperationalError: Unable to get from session')
raise
oidc_config = OIDCConfig.objects.get(id=idp_id)
q = Request(oidc_config.oidc_client.provider_info['userinfo_endpoint'])
req = Request(
oidc_config.oidc_client.provider_info['userinfo_endpoint']
)
auth = (token_type + ' ' + access_token)
q.add_header('Authorization', auth)
req.add_header('Authorization', auth)
userinfo_bytes = urlopen(q).read()
userinfo_bytes = urlopen(req).read()
return json.loads(userinfo_bytes.decode('UTF-8'))
def authenticate(self, request, token=None):
......@@ -90,7 +88,8 @@ class OIDCTokenAuthBackend(object):
user_info = self.get_user_info(request, token)
try:
user = models.User.objects.get(
sub=user_info['sub'])
sub=user_info['sub']
)
return user
except ObjectDoesNotExist:
......
import json
import logging
from django.contrib.auth import authenticate, login, logout
from django.db.utils import OperationalError
from django.http import HttpResponse
from django.shortcuts import redirect
from django.views import View
from oic import rndstr
from oic.oic.message import AuthorizationResponse
from rest_framework import generics, views
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
import json
from ...logging import get_logger
from oic import rndstr
from oic.oic.message import AuthorizationResponse
from .models import OIDCConfig, default_idp
from .serializers import AuthInfoSerializer
logger = get_logger(__name__)
LOGGER = logging.getLogger(__name__)
idp_cookie_name = 'idp_id'
IDP_COOKIE_NAME = 'idp_id'
def idp_id_from_request(request):
id = request.COOKIES.get(idp_cookie_name, None)
if id is not None:
return id
else:
return default_idp().id
idp_id = request.COOKIES.get(IDP_COOKIE_NAME, None)
if idp_id is not None:
return idp_id
return default_idp().id
def get_session(request, key, default):
try:
value = request.session.get(key, None)
except OperationalError:
logger.error('Operational: Error getting from session')
LOGGER.error('Operational: Error getting from session')
raise
if value is not None:
return value
else:
return default
return default
def set_session(request, key, value):
try:
value = request.session[key] = value
except OperationalError:
logger.error('Operational: Error setting in session')
LOGGER.error('Operational: Error setting in session')
raise
class Auth(View):
def get(self, request, **kwargs):
def get(self, request):
try:
state = rndstr()
......@@ -67,18 +66,18 @@ class Auth(View):
)
)
except Exception:
logger.error('Malformed oidc config: {}'.format(oidc_config))
LOGGER.error('Malformed oidc config: {}'.format(oidc_config))
raise
except Exception as e:
logger.error('request: {}'.format(e))
except Exception as exception:
LOGGER.error('request: {}'.format(exception))
# the error is deleted from the session when the state is delivered
request.session['error'] = 'Server Error'
return redirect('/')
class AuthCallback(View):
def get(self, request, **kwargs):
def get(self, request):
try:
state = get_session(request, 'state', None)
idp_id = get_session(request, 'idp_id', default_idp().id)
......@@ -90,7 +89,7 @@ class AuthCallback(View):
)
if not state == aresp['state']:
logger.error('states do not match')
LOGGER.error('states do not match')
raise Exception('States do not match')
ac_token_response = (
......@@ -123,30 +122,32 @@ class AuthCallback(View):
if user is None:
# authentication failed -> "401"
logger.error('User failed to log in'.format(request.user))
LOGGER.error('User failed to log in')
request.session['error'] = 'Login failed'
# response = HttpResponse('Unauthorized', status=401)
elif not user.is_active:
# user is deactivated -> "403"
logger.info('{} tried to log in'.format(user))
LOGGER.info('{} tried to log in'.format(user))
request.session['error'] = 'Account deactivated'
# response = HttpResponse('Forbidden', status=403)
else:
# user authenticated -> back to frontend
login(request, user)
LOGGER.debug('authenticated {}'.format(user))
response.set_cookie('sessionid', request.COOKIES['sessionid'])
return response
except Exception as e:
logger.error('request: {}'.format(e))
except Exception as exception:
LOGGER.error('request: {}'.format(exception))
# the error is deleted from the session when the state is delivered
request.session['error'] = 'Server Error'
return redirect('/')
class LogoutView(views.APIView):
def post(self, request, format=None):
def post(self, request):
LOGGER.debug('logged out {}'.format(request.user))
logout(request)
return Response({})
......
......@@ -2,15 +2,15 @@
from rest_framework import generics, views, status
from rest_framework.authentication import TokenAuthentication
from rest_framework.response import Response
from ..models import rabbitmq_instance
from ..models import RABBITMQ_INSTANCE
from . import serializers
# authentication class for the client api
authentication_classes = (TokenAuthentication, )
AUTHENTICATION_CLASSES = (TokenAuthentication, )
class DeploymentsView(generics.RetrieveAPIView):
authentication_classes = authentication_classes
authentication_classes = AUTHENTICATION_CLASSES
serializer_class = serializers.SiteSerializer
def get_object(self):
......@@ -19,7 +19,7 @@ class DeploymentsView(generics.RetrieveAPIView):
# the client has to fetch the configuration (like services etc.) here
class ConfigurationView(generics.ListAPIView):
authentication_classes = authentication_classes
authentication_classes = AUTHENTICATION_CLASSES
serializer_class = serializers.ServiceSerializer
def get_queryset(self):
......@@ -27,14 +27,14 @@ class ConfigurationView(generics.ListAPIView):
# we update the rabbitmq permission here, so the
# client can access all of his services, even new ones
rabbitmq_instance().update_site(site)
RABBITMQ_INSTANCE.update_site(site)
return site.services.all()
class AckView(views.APIView):
authentication_classes = authentication_classes
authentication_classes = AUTHENTICATION_CLASSES
def delete(self, request, id=None, format=None):
def delete(self, request, id=None):
# find the corresponding task for this item
for item in request.user.site.task_items.all():
if item.task.id == int(id):
......
......@@ -6,8 +6,8 @@ from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework import status
from . import serializers, models as frontend_models
from .. import models
from django_backend.backend.frontend import serializers, models as frontend_models
from django_backend.backend import models
import logging
logger = logging.getLogger(__name__)
......@@ -100,16 +100,15 @@ class SSHPublicKeyView(views.APIView):
class DeploymentView(views.APIView):
def post(self, request, format=None):
if (
'type' not in request.data or
'key' not in request.data or
'service' not in request.data
):
):
logger.error(
'Deployment api got invalid request {}'.format(
request.data))
'Deployment api got invalid request {}'.format(
request.data))
return _api_error_response()
request_type = request.data['type']
......@@ -120,6 +119,7 @@ class DeploymentView(views.APIView):
name=request.data['key'])
# check if there is already an deployment
if not request.user.deployments.filter(service=request_service).exists():oeuaoeuaoeuoaeuoeauoaeuoeuaoeuoaeuaoeua
try:
deployment = request.user.deployments.get(service=request_service)
except Exception:
......@@ -127,8 +127,9 @@ class DeploymentView(views.APIView):
return _api_error_response()
deployment = models.Deployment(
user=request.user,
service=request_service)
user=request.user,
service=request_service,
)
deployment.save()
if request_type == 'add':
......
import logging
from logging import Formatter, FileHandler, StreamHandler, getLogger
import sys
logger_dir = './logs/'
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
LOGGER_NAME = 'django_backend.backend'
LOGGER_DIR = './logs/'
FORMATTER = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
error_fh = logging.FileHandler(logger_dir + 'error.log')
error_fh.setLevel(logging.ERROR)
error_fh.setFormatter(formatter)
ERROR_FH = FileHandler(LOGGER_DIR + 'error.log')
ERROR_FH.setLevel('ERROR')
ERROR_FH.setFormatter(FORMATTER)
info_fh = logging.FileHandler(logger_dir + 'info.log')
info_fh.setLevel(logging.INFO)
info_fh.setFormatter(formatter)
INFO_FH = FileHandler(LOGGER_DIR + 'info.log')
INFO_FH.setLevel('INFO')
INFO_FH.setFormatter(FORMATTER)
debug_fh = logging.FileHandler(logger_dir + 'debug.log')
debug_fh.setLevel(logging.DEBUG)
debug_fh.setFormatter(formatter)
DEBUG_FH = FileHandler(LOGGER_DIR + 'debug.log')
DEBUG_FH.setLevel('DEBUG')
DEBUG_FH.setFormatter(FORMATTER)
# for the console
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.INFO)
ch.setFormatter(formatter)
CH = StreamHandler(sys.stdout)
CH.setLevel('INFO')
CH.setFormatter(FORMATTER)
def setup_logger(name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
def setup_logger():
logger = getLogger(LOGGER_NAME)
logger.setLevel('DEBUG')
# add all handlers
logger.addHandler(error_fh)
logger.addHandler(info_fh)
logger.addHandler(ch)
logger.addHandler(debug_fh)
logger.addHandler(ERROR_FH)
logger.addHandler(INFO_FH)
logger.addHandler(CH)
logger.addHandler(DEBUG_FH)
logger.info('STARTED LOGGER {}'.format(name))
def get_logger(name):
return logging.getLogger(name)
setup_logger('django_backend.backend')
logger.info('STARTED LOGGER {}'.format(LOGGER_NAME))
# django senders need their arguments
# pylint: disable=unused-argument
import json
import logging
import requests
from requests.auth import HTTPBasicAuth
import pika
from django.conf import settings
from django.contrib.auth.models import AbstractUser, Group
from django.db import models
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from requests.auth import HTTPBasicAuth
from rest_framework.authtoken.models import Token
import json
import pika
import requests
from .logging import get_logger
from .logging import setup_logger
logger = get_logger(__name__)
# we start the logger here
setup_logger()
LOGGER = logging.getLogger(__name__)
# clients are registerred at rabbitmq, when they are assigned to a site
......@@ -49,14 +55,6 @@ class RabbitMQInstance(models.Model):
def msg(self, msg):
return '[RabbitMQ:{}] {}'.format(self.host, msg)
@property
def api(self):
return 'http://{}:{}/{}'.format(
self.host,
self.port,
self.path,
)
@property
def auth(self):
return HTTPBasicAuth(
......@@ -82,7 +80,7 @@ class RabbitMQInstance(models.Model):
self.rabbitmq_connection = pika.BlockingConnection(
rabbitmqconnection_properties
)
logger.debug(self.msg('opened connection'))
LOGGER.debug(self.msg('opened connection'))
return self.rabbitmq_connection
......@@ -95,36 +93,42 @@ class RabbitMQInstance(models.Model):
durable=True,
exchange_type='topic')
self.rabbitmq_channel.confirm_delivery()
logger.debug(self.msg('opened channel'))
LOGGER.debug(self.msg('opened channel'))
return self.rabbitmq_channel
def get_uri(self, path):
return '{}/{}'.format(self.api, path)
api = 'http://{}:{}/{}'.format(
self.host,
self.port,
self.path,
)
return '{}/{}'.format(api, path)
def rest_get(self, api_path):
r = requests.get(
req = requests.get(
self.get_uri(api_path),
auth=self.auth)
r.raise_for_status()
return r.json()
req.raise_for_status()
return req.json()
# send a rest call with path and data to the rest interface of
# the rabbitmq instance
def rest_put(self, api_path, data):
r = requests.put(
req = requests.put(
self.get_uri(api_path),
json=data,
auth=self.auth)
r.raise_for_status()
return r
req.raise_for_status()
return req
def rest_del(self, api_path):
r = requests.delete(
req = requests.delete(
self.get_uri(api_path),
auth=self.auth)
r.raise_for_status()
return r
req.raise_for_status()
return req
def set_topic_permissions(self, site):
username = site.client.username
......@@ -136,19 +140,19 @@ class RabbitMQInstance(models.Model):
# set permissions for the correct topics
# we construct a regex to match the services of the site
services = ''
omitBar = True
omit_bar = True
for service in site.services.all():
prefix = '|'
if omitBar:
if omit_bar:
prefix = ''
omitBar = False
omit_bar = False
services = services + prefix + service.name
set_topic_permission_data = {
'exchange': self.exchange,
'write': '^$',
'read': '^service\.({})$'.format(services),
'read': r'^service\.({})$'.format(services),
}
return self.rest_put(path, set_topic_permission_data)
......@@ -160,7 +164,7 @@ class RabbitMQInstance(models.Model):
self.vhost,
username,
)
permission = '^(amq\.gen.*|{})'.format(self.exchange)
permission = r'^(amq\.gen.*|{})'.format(self.exchange)
set_permission_data = {
'configure': permission,
'write': permission,
......@@ -194,14 +198,14 @@ class RabbitMQInstance(models.Model):
self.create_user(site)
self.set_permissions(site)
self.set_topic_permissions(site)
logger.info(self.msg('registered {}'.format(site.client)))
LOGGER.info(self.msg('registered {}'.format(site.client)))
def update_site(self, site):
self.set_topic_permissions(site)
logger.info(self.msg('updated permissions for {}'.format(site.client)))
LOGGER.info(self.msg('updated permissions for {}'.format(site.client)))
def deregister_site(self, site):
logger.info(self.msg('deregistered {}'.format(site.client)))
LOGGER.info(self.msg('deregistered {}'.format(site.client)))
def is_client_connected(self, site):
connections = self.rest_get("connections/")
......@@ -211,12 +215,9 @@ class RabbitMQInstance(models.Model):
return len(clients_for_site) > 0
def disconnect(self):
logger.debug(self.msg('closing connection'))
LOGGER.debug(self.msg('closing connection'))
self.connection.close()
def service_routing_key(self, service):
return 'service.' + service.name
def online_clients(self, service):
return [site
for site in service.site.all()
......@@ -233,8 +234,11 @@ class RabbitMQInstance(models.Model):
)
def rabbitmq_instance():
return RabbitMQInstance.objects.get(is_active=True)
def service_routing_key(service):
return 'service.' + service.name
RABBITMQ_INSTANCE = RabbitMQInstance.objects.filter(is_active=True).first()
class User(AbstractUser):
......@@ -274,12 +278,14 @@ class User(AbstractUser):
def __str__(self):
if self.user_type == 'admin':
return 'ADMIN {}'.format(self.username)
if self.user_type == 'oidcuser':
elif self.user_type == 'oidcuser':
if not self.is_active:
return 'DEACTIVATED USER {}'.format(self.username)
return 'USER {}'.format(self.username)
if self.user_type == 'apiclient':
elif self.user_type == 'apiclient':
return 'APICLIENT {}@{}'.format(self.username, self.site)
else:
raise Exception()
def msg(self, msg):
return '[{}] {}'.format(self, msg)
......@@ -288,7 +294,7 @@ class User(AbstractUser):
def remove(self):
if self.user_type == 'oidcuser':
self.deactivate()
logger.info(self.msg('Deleting'))
LOGGER.info(self.msg('Deleting'))
# TODO: deleting the user brings problems:
# the deletion cascades down to DeploymentTask and DeploymentTaskItem
......@@ -297,7 +303,7 @@ class User(AbstractUser):