Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
settings.py 9.61 KiB
"""
Django settings for tmss project.

Generated by 'django-admin startproject' using Django 2.0.6.

For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""

import os
import logging
from lofar.common import dbcredentials, isDevelopmentEnvironment

logger = logging.getLogger(__name__)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[%(server_time)s] %(message)s',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
        'django_auth_ldap': {
            'handlers': ['console'],
            'level': 'INFO',
        },
    }
}

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '-&$!kx$_0)u1x#zk9w^^81hfssaover2(8wdq_8n8n3u(8=-9n'       # todo: set something new here for production !!!


# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'lofar.sas.tmss.tmss.tmssapp',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'django_jsonforms',
    'django_json_widget',
    'jsoneditor',
    'drf_yasg',
    'django_filters',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # 'mozilla_django_oidc.middleware.SessionRefresh',
]

ROOT_URLCONF = 'lofar.sas.tmss.tmss.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'lofar.sas.tmss.tmss.wsgi.application'

# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases

# Read Postgres DB settings

# this requires a config file in ~/.lofar/dbcredentials/tmss.ini
# if no such file exists then it is automatically created.
# It is also possible to set another credentials-name via the TMSS_DBCREDENTIALS env-var for testing for example.
#
# contents should be like this (adapt as needed):
#
# [database:tmss]
# type = postgresql
# host = localhost
# database = <your_tmss_database_name>
# port = 5432
# user = <your_tmss_user_name>
# password = <your_tmss_password>

creds_name = os.environ.get('TMSS_DBCREDENTIALS', 'tmss')
django_db_credentials = dbcredentials.DBCredentials().get(creds_name)
logger.debug("TMSS Django settings: Using dbcreds '%s' for django database: %s",
            creds_name, django_db_credentials.stringWithHiddenPassword())

DATABASES = {
    'default': {
        # Postgres:
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': django_db_credentials.database,
        'USER': django_db_credentials.user,
        'PASSWORD': django_db_credentials.password,
        'HOST': django_db_credentials.host,
        'PORT': django_db_credentials.port,
        }
    }

REST_FRAMEWORK = {
    # Authentication, see also if-tree below for Open-ID vs LDAP configuration
    'DEFAULT_AUTHENTICATION_CLASSES': [],
    'DEFAULT_PERMISSION_CLASSES': [],
    'PAGE_SIZE': 50,
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'DEFAULT_FILTER_BACKENDS': (
        # allows ?field=value filtering in URLs
        # (fields allowed for filtering must be annotated in viewsets using filter_fields = ('field', ...))
        'django_filters.rest_framework.DjangoFilterBackend',

        # allows ?ordering=[-]field to order list results
        'rest_framework.filters.OrderingFilter',
    ),
}

# AUTHENTICATION: simple LDAP, or OpenID
if "OIDC_RP_CLIENT_ID" in os.environ.keys():

    INSTALLED_APPS.append('mozilla_django_oidc')  # Load after auth
    REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append('mozilla_django_oidc.contrib.drf.OIDCAuthentication')
    REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'].append('rest_framework.permissions.IsAuthenticated')

    # OPEN-ID CONNECT
    OIDC_DRF_AUTH_BACKEND = 'mozilla_django_oidc.auth.OIDCAuthenticationBackend'

    # For talking to Mozilla Identity Provider:
    OIDC_RP_SCOPES = "openid email profile"  # todo: groups are not a standard scope, how to handle those?
    OIDC_RP_CLIENT_ID = os.environ.get('OIDC_RP_CLIENT_ID', '2')  # Secret, do not put real credentials on Git
    OIDC_RP_CLIENT_SECRET = os.environ.get('OIDC_RP_CLIENT_SECRET',
                                           'secret')  # Secret, do not put real credentials on Git
    OIDC_ENDPOINT_HOST = os.environ.get('OIDC_ENDPOINT_HOST', 'tmss_test_oidc')
    OIDC_OP_AUTHORIZATION_ENDPOINT = "http://%s:8088/openid/authorize" % OIDC_ENDPOINT_HOST
    OIDC_OP_TOKEN_ENDPOINT = "http://%s:8088/openid/token" % OIDC_ENDPOINT_HOST
    OIDC_OP_USER_ENDPOINT = "http://%s:8088/openid/userinfo" % OIDC_ENDPOINT_HOST

    AUTHENTICATION_BACKENDS = ('mozilla_django_oidc.auth.OIDCAuthenticationBackend',)
elif "TMSS_LDAPCREDENTIALS" in os.environ.keys():
    # plain LDAP
    import ldap

    REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append('rest_framework.authentication.BasicAuthentication')
    REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append('rest_framework.authentication.SessionAuthentication')
    REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'].append('rest_framework.permissions.IsAuthenticated')

    # LDAP
    ldap_creds_name = os.environ.get('TMSS_LDAPCREDENTIALS', 'tmss_ldap')
    django_ldap_credentials = dbcredentials.DBCredentials().get(ldap_creds_name)
    logger.debug("TMSS Django settings: Using dbcreds '%s' for ldap authentication: %s",
                ldap_creds_name, django_ldap_credentials.stringWithHiddenPassword())

    AUTH_LDAP_GLOBAL_OPTIONS = {ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_NEVER}  # cert still expired?
    AUTH_LDAP_CONNECTION_OPTIONS = {ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_NEVER}  # cert still expired?
    protocol = 'ldap://' if isDevelopmentEnvironment() else 'ldaps://'
    AUTH_LDAP_SERVER_URI = "%s%s:%s" % (protocol, django_ldap_credentials.host, django_ldap_credentials.port)
    AUTH_LDAP_USER_DN_TEMPLATE = "cn=%(user)s,ou=Users,o=lofar,c=eu"

    AUTH_LDAP_USER_ATTR_MAP = {
        "first_name": "givenName",
        "last_name": "sn",
        "email": "mail"
    }

    AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend',
                               'django.contrib.auth.backends.ModelBackend')
else:
    REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'].append('rest_framework.permissions.AllowAny')
    logger.warning("No authentication configured! please set either OIDC_RP_CLIENT_ID or TMSS_LDAPCREDENTIALS environment variable.")


LOGIN_REDIRECT_URL = "/api/"
LOGIN_REDIRECT_URL_FAILURE = "/api/"
LOGOUT_REDIRECT_URL = "/api/"
LOGOUT_REDIRECT_URL_FAILURE = "/api/"


# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = False  # We don't want timezone support since everything is UTC anyway and this caused trouble in the past


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/

STATIC_URL = '/static/'


# Setup support for proxy headers
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')