# This file is sourced by "execfile" from django settings # Example of django settings.py: # # (...) # PROJECT_NAME = 'name' # INSTALLED_APPS += ('mellon',) # SAML2 authentication # execfile('/usr/lib/hoho/debian_config_common.py') # execfile('/etc/%s/settings.py' % PROJECT_NAME) import os import warnings import django from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured import hobo.logger DEBUG = False with open('/etc/%s/secret' % PROJECT_NAME) as fd: SECRET_KEY = fd.read().strip() ADMINS = (('Tous', 'root@localhost'),) EMAIL_SUBJECT_PREFIX = '' # sockets default timeout can be set to a small value in another thread by kombu # https://github.com/celery/kombu/issues/838 # This prevents sockets created in smtplib to rely on the default timeout # by setting their timeout value to 10 seconds. EMAIL_TIMEOUT = 10.0 # send the SMTP Date header of email messages in the local time zone # (since Django 1.11) EMAIL_USE_LOCALTIME = True # For high availability installations with multiple instances of Publik # components, one should disable cron jobs execution on secondary servers; # set the following variable True disables all tenant_commands launched with # option "--all-tenants". DISABLE_CRON_JOBS = False # mode for newly updated files FILE_UPLOAD_PERMISSIONS = 0o644 DEBUG_LOG_PATH = '/var/log/%s/debug' % PROJECT_NAME DEBUG_LOG_FORMAT = ( '%(asctime)s \x1f%(tenant)s \x1f%(ip)s \x1f%(user)r \x1f%(request_id)s \x1f' '%(levelname)s \x1f%(name)s \x1f%(message)s' ) DEBUG_PROVISIONNING_LOG_PATH = '/var/log/%s/provisionning-debug' % PROJECT_NAME DISABLE_GLOBAL_HANDLERS = os.environ.get('DISABLE_GLOBAL_HANDLERS') == '1' LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', }, 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, 'request_context': { '()': 'hobo.logger.RequestContextFilter', }, 'force_debug': { '()': 'hobo.logger.ForceDebugFilter', }, 'debug_log': { '()': 'hobo.logger.DebugLogFilter', }, 'clamp_to_warning': { '()': 'hobo.logger.ClampLogLevel', 'level': 'WARNING', }, }, 'formatters': { 'syslog': { 'format': '%(application)s %(levelname)s %(tenant)s %(ip)s %(user)s %(request_id)s' ' %(message)s', }, 'debug': { 'format': DEBUG_LOG_FORMAT, }, 'syslog_no_filter': { 'format': '%(levelname)s %(message)s', }, }, 'handlers': { 'syslog': { 'level': 'INFO', 'address': '/dev/log', 'class': 'logging.handlers.SysLogHandler', 'formatter': 'syslog', 'filters': ['request_context'], }, 'syslog_no_filter': { 'level': 'INFO', 'address': '/dev/log', 'class': 'logging.handlers.SysLogHandler', 'formatter': 'syslog_no_filter', }, 'mail_admins': { 'level': 'ERROR', 'class': 'hobo.multitenant.log.AdminEmailHandler', 'include_html': True, }, 'null': { 'class': 'logging.NullHandler', }, 'debug': { 'level': 'DEBUG', 'class': 'hobo.logger.TimedRotatingFileHandler', 'formatter': 'debug', 'filename': DEBUG_LOG_PATH, 'when': 'midnight', 'backupCount': 1, 'interval': 1, 'filters': ['request_context', 'debug_log'], }, }, 'loggers': { 'django.db': { # even when debugging seeing SQL queries is too much 'level': 'INFO', }, 'django': { # Override Django default values 'handlers': [], 'level': 'NOTSET', 'propagate': True, }, 'django.server': { # Override Django 1.8 default values 'handlers': [], 'level': 'NOTSET', 'propagate': True, }, 'django.request': { # Override Django default values 'handlers': [], 'level': 'NOTSET', 'propagate': True, }, 'django.security': { # Override Django default values 'handlers': [], 'level': 'NOTSET', 'propagate': True, }, 'django.security.SuspiciousFileOperation': { 'filters': ['clamp_to_warning'], }, 'django.security.DisallowedRedirect': { 'filters': ['clamp_to_warning'], }, 'django.core.exceptions.DisallowedHost': { 'filters': ['clamp_to_warning'], }, 'django.template': { # too much logs on DEBUG level 'handlers': [], 'level': 'INFO', 'propagate': True, }, # lasso has the bad habit of logging everything as errors 'Lasso': { 'filters': ['force_debug'], }, 'libxml2': { 'filters': ['force_debug'], }, 'libxmlsec': { 'filters': ['force_debug'], }, # log py.warnings to syslog 'py.warnings': { 'handlers': [] if DISABLE_GLOBAL_HANDLERS else ['syslog_no_filter'], 'level': 'WARNING', 'propagate': False, }, '': { 'level': 'DEBUG', 'filters': ['request_context'], 'handlers': ([] if DISABLE_GLOBAL_HANDLERS else ['syslog']) + ['mail_admins', 'debug'], }, }, } # Journald support if os.path.exists('/run/systemd/journal/socket') and not DISABLE_GLOBAL_HANDLERS: try: from systemd import journal except ImportError: pass else: LOGGING['handlers']['journald'] = { 'level': 'INFO', 'class': 'hobo.journal.JournalHandler', 'filters': ['request_context'], 'formatter': 'syslog', } LOGGING['loggers']['']['handlers'].remove('syslog') LOGGING['loggers']['']['handlers'].append('journald') elif not os.path.exists('/dev/log') and not DISABLE_GLOBAL_HANDLERS: # if three's no syslog (for example when building a docker image), remove # those loggers. LOGGING['loggers']['']['handlers'].remove('syslog') LOGGING['loggers']['py.warnings']['handlers'].remove('syslog_no_filter') del LOGGING['handlers']['syslog'] del LOGGING['handlers']['syslog_no_filter'] ETC_DIR = '/etc/%s' % PROJECT_NAME VAR_DIR = '/var/lib/%s' % PROJECT_NAME # collecstatic destination STATIC_ROOT = os.path.join(VAR_DIR, 'collectstatic') # template settings assert len(TEMPLATES) assert TEMPLATES[0]['BACKEND'] == 'django.template.backends.django.DjangoTemplates' if not 'loaders' in TEMPLATES[0]['OPTIONS']: TEMPLATES[0]['APP_DIRS'] = False TEMPLATES[0]['OPTIONS']['loaders'] = [ 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ] if PROJECT_NAME != 'wcs': TEMPLATES[0]['OPTIONS']['loaders'].insert(0, 'hobo.multitenant.template_loader.FilesystemLoader') if not 'django.template.context_processors.request' in TEMPLATES[0]['OPTIONS']['context_processors']: TEMPLATES[0]['OPTIONS']['context_processors'].insert(0, 'django.template.context_processors.request') TEMPLATES[0]['OPTIONS']['context_processors'] = [ 'hobo.context_processors.template_vars', 'hobo.context_processors.theme_base', 'hobo.context_processors.portal_agent_url', 'hobo.context_processors.user_urls', ] + TEMPLATES[0]['OPTIONS']['context_processors'] # needed by hobo.context_processors.theme_base: # THEME_SKELETON_URL = 'https://www.example.net/__skeleton__' # Browsers may ensure that cookies are only sent under an HTTPS connection CSRF_COOKIE_SECURE = True CSRF_COOKIE_HTTPONLY = True SESSION_COOKIE_SECURE = True SESSION_EXPIRE_AT_BROWSER_CLOSE = True SESSION_COOKIE_AGE = 36000 # 10h CSRF_COOKIE_SAMESITE = None # Apply sessionNotOnOrAfter on session expiration date SESSION_ENGINE = 'mellon.sessions_backends.cached_db' # make it easier to use runserver behind nginx as reverse proxy SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') if 'MIDDLEWARE' not in globals(): MIDDLEWARE = global_settings.MIDDLEWARE MIDDLEWARE = ( 'hobo.middleware.VersionMiddleware', # /__version__ 'hobo.middleware.cors.CORSMiddleware', 'hobo.middleware.maintenance.MaintenanceMiddleware', ) + MIDDLEWARE if PROJECT_NAME != 'wcs': MIDDLEWARE = ('hobo.middleware.RobotsTxtMiddleware',) + MIDDLEWARE if PROJECT_NAME != 'wcs' and 'authentic2' not in INSTALLED_APPS: MIDDLEWARE = MIDDLEWARE + ( 'mellon.middleware.PassiveAuthenticationMiddleware', 'hobo.provisionning.middleware.ProvisionningMiddleware', ) if 'authentic2' in INSTALLED_APPS: MIDDLEWARE = MIDDLEWARE + ('hobo.agent.authentic2.middleware.ProvisionningMiddleware',) # Allow big provisionning messages DATA_UPLOAD_MAX_MEMORY_SIZE = 50_000_000 if PROJECT_NAME != 'wcs': # multitenant adaptations TENANT_BASE = os.path.join(VAR_DIR, 'tenants') TENANT_MODEL = 'multitenant.Tenant' MIDDLEWARE = ( 'hobo.multitenant.middleware.TenantMiddleware', 'hobo.middleware.CookiesSameSiteFixMiddleware', 'hobo.middleware.debug.InternalIPMiddleware', ) + MIDDLEWARE DATABASES = { 'default': { 'ENGINE': 'tenant_schemas.postgresql_backend', 'NAME': PROJECT_NAME.replace('-', '_'), } } DATABASE_ROUTERS = ('tenant_schemas.routers.TenantSyncRouter',) TENANT_SETTINGS_LOADERS = ( 'hobo.multitenant.settings_loaders.TemplateVars', 'hobo.multitenant.settings_loaders.KnownServices', 'hobo.multitenant.settings_loaders.LegacyURLSSettings', 'hobo.multitenant.settings_loaders.ThemeSettings', 'hobo.multitenant.settings_loaders.CORSSettings', 'hobo.multitenant.settings_loaders.SharedThemeSettings', 'hobo.multitenant.settings_loaders.Mellon', 'hobo.multitenant.settings_loaders.SiteBaseUrl', 'hobo.multitenant.settings_loaders.CookieNames', 'hobo.multitenant.settings_loaders.SettingsJSON', 'hobo.multitenant.settings_loaders.SettingsVars', 'hobo.multitenant.settings_loaders.BackofficeLoginHint', ) # templates in /templates TENANT_TEMPLATE_DIRS = (TENANT_BASE,) # /media in /media DEFAULT_FILE_STORAGE = 'hobo.multitenant.storage.TenantFileSystemStorage' # cache by tenant CACHES = { 'default': { 'BACKEND': 'hobo.multitenant.cache.TenantCache', # add a real Django cache backend, with its parameters if needed 'REAL_BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } # haystack by tenant HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'hobo.multitenant.haystack.WhooshEngine', } } # multitenant SHARED_APPS/TENANT_APPS/INSTALLED_APPS organization SHARED_APPS = () INSTALLED_APPS = ('hobo.agent.common',) + INSTALLED_APPS TENANT_APPS = INSTALLED_APPS INSTALLED_APPS = ('hobo.multitenant',) + INSTALLED_APPS # SAML2: search IdP in if 'authentic2' not in INSTALLED_APPS: MELLON_ADAPTER = ('hobo.multitenant.mellon.MellonAdapter',) if PROJECT_NAME in ('wcs', 'combo'): TEMPLATES[0]['OPTIONS'].setdefault('builtins', []).append('hobo.templatetags.hobo') if 'authentic2' not in INSTALLED_APPS: MELLON_DEFAULT_ASSERTION_CONSUMER_BINDING = 'artifact' MELLON_OPENED_SESSION_COOKIE_NAME = 'A2_OPENED_SESSION' MELLON_ADD_AUTHNREQUEST_NEXT_URL_EXTENSION = True MIDDLEWARE = ( 'hobo.middleware.utils.StoreRequestMiddleware', 'hobo.middleware.xforwardedfor.XForwardedForMiddleware', ) + MIDDLEWARE MIDDLEWARE = MIDDLEWARE + ('hobo.middleware.PrometheusStatsMiddleware',) HOBO_MANAGER_HOMEPAGE_URL_VAR = 'portal_agent_url' HOBO_MANAGER_HOMEPAGE_TITLE_VAR = 'portal_agent_title' # Authentic2 role attributes for Publik A2_MANAGER_ROLE_FORM_CLASS = 'hobo.agent.authentic2.role_forms.RoleForm' # Locale and timezone LANGUAGE_CODE = 'fr-fr' TIME_ZONE = 'Europe/Paris' LANGUAGES = (('fr', u'Fran\xe7ais'),) USE_L10N = True USE_TZ = True # Celery configuration BROKER_URL = 'amqp://' BROKER_TASK_EXPIRES = 600 STATICS_HASH_COUNTER = '/var/lib/publik/statics-counter' # Django Rest Framework: allow only Publik-signed URLs if 'rest_framework' in INSTALLED_APPS: if 'REST_FRAMEWORK' not in globals(): REST_FRAMEWORK = {} REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ('hobo.rest_authentication.PublikAuthentication',) REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.IsAuthenticated',) REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'] = ('rest_framework.renderers.JSONRenderer',) HOBO_ANONYMOUS_SERVICE_USER_CLASS = 'hobo.rest_authentication.AnonymousAdminServiceUser' THEMES_DIRECTORY = '/usr/share/publik/themes/' USE_X_FORWARDED_FOR = True EMAIL_BACKEND = 'hobo.emails.backend.EmailBackend'