settings.py 42.2 KB
Newer Older
1
"""Django settings for failmap project.
2

3 4 5 6
You do not need to edit the settings listed below.

For example, you should not need to change the DEBUG setting here, ever. For this you can use
direnv, which will change your environment settings when you enter this projects directory.
7 8 9 10 11 12 13 14

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

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""
import os
Elger Jonker's avatar
Elger Jonker committed
15 16
# required until fixed: https://github.com/jazzband/django-constance/issues/263
from collections import OrderedDict
17
from datetime import timedelta
18

Johan Bloemberg's avatar
Johan Bloemberg committed
19 20
import raven
import raven.contrib.celery
Elger Jonker's avatar
lint  
Elger Jonker committed
21
from django.utils.translation import gettext_lazy as _
Johan Bloemberg's avatar
Johan Bloemberg committed
22 23 24 25
from pkg_resources import get_distribution

__version__ = get_distribution(__name__.split('.', 1)[0]).version

26
# this application can run in 3 modes: admin, interactive and frontend
Johan Bloemberg's avatar
Johan Bloemberg committed
27
# 'admin' exposes all routes and uses no caching. It should be restricted in access.
28 29 30 31 32 33 34 35 36 37 38
# 'interactive' does not expose administrative urls, but does allow write access. Access should be
# restricted but can be less restricted then admin.
# 'frontend' only exposes the visitor facing routes and serves with cache headers. It does not
# allow write access to the database. Access can be unrestricted but is preferably behind caching
# proxy.

# for usability default to most functional mode
APPLICATION_MODE = os.environ.get('APPLICATION_MODE', 'admin')

ADMIN = bool(APPLICATION_MODE == 'admin')
INTERACTIVE = bool(APPLICATION_MODE == 'interactive')
39

40
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
41 42 43 44 45
# BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Changed BASE_DIR so templates need to include the module and such. The idea
# was that otherwise the wrong template could be used when they have the same name
# over different dirs. Is this correct?
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
46 47 48 49 50

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
51
SECRET_KEY = os.environ.get('SECRET_KEY', 'ditisgeengeheimvriendachtjedatditeenwachtwoordwas')
52 53

# SECURITY WARNING: don't run with debug turned on in production!
54
DEBUG = os.environ.get('DEBUG', False)
55

56
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1,::1,100.66.10.138,100.66.10.142').split(',')
57

Johan Bloemberg's avatar
Johan Bloemberg committed
58 59 60
# allow better debugging for these clients
# https://docs.djangoproject.com/en/1.11/ref/settings/#internal-ips
INTERNAL_IPS = ['localhost', '127.0.0.1', '::1']
61 62 63 64

# Application definition

INSTALLED_APPS = [
65
    # needs to be before jet and admin to extend admin/base.html template
66 67
    'dal',
    'dal_select2',
68
    'failmap.app',
69 70
    'failmap.hypersh',
    'django_fsm_log',
71
    'adminsortable2',
72
    # Jet admin dashboard
73 74
    'jet.dashboard',
    'jet',
75
    'nested_admin',
76 77 78 79 80 81
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
82
    'import_export',
83
    'failmap.fail',
84
    'failmap.organizations.apps.OrganizationsConfig',  # because some signals need this.
85 86
    'failmap.scanners',
    'failmap.map',
87
    'failmap.game',
88
    'failmap.monitoryour',
89 90
    'django_countries',
    'django.contrib.admindocs',
91
    'django.contrib.humanize',
92
    'compressor',
93
    'django_celery_beat',
Johan Bloemberg's avatar
Johan Bloemberg committed
94
    'proxy',
95
    'django_statsd',
96 97
    'constance',
    'constance.backends.database',
98
    'leaflet',
99
    'djgeojson',
Elger Jonker's avatar
lint  
Elger Jonker committed
100
    'crispy_forms',  # for the game
101 102 103 104

    # django helpdesk requirements:
    'django.contrib.sites',  # Required for determining domain url for use in emails
    'markdown_deux',  # Required for Knowledgebase item formatting
Elger Jonker's avatar
lint  
Elger Jonker committed
105
    'bootstrapform',  # Required for nicer formatting of forms with the default templates
106 107
    'helpdesk',  # This is us!

108
    # 'mapwidgets', # we don't support gdal, as it's not in alpine stable yet.
109
    'colorful',
110
    'django_select2',
111
    # others:
112
    # 'mapwidgets',  no gdal available yet, try again later
113
    # 'cachalot',  # query cache, is not faster.
114
    # 'silk'  # works great for debugging.
115 116
]

Johan Bloemberg's avatar
Johan Bloemberg committed
117
try:
118 119
    # hack to disable django_uwsgi app as it currently conflicts with compressor
    # https://github.com/django-compressor/django-compressor/issues/881
Johan Bloemberg's avatar
Johan Bloemberg committed
120
    if not os.environ.get('COMPRESS', False):
121
        import django_uwsgi  # NOQA
122

123
        INSTALLED_APPS += ['django_uwsgi', ]
Johan Bloemberg's avatar
Johan Bloemberg committed
124 125 126 127
except ImportError:
    # only configure uwsgi app if installed (ie: production environment)
    pass

128 129
# don't run this in production
try:
130
    import django_extensions  # NOQA
131

132 133 134 135
    INSTALLED_APPS += ['django_extensions']
except ImportError:
    pass

Elger Jonker's avatar
Elger Jonker committed
136
MIDDLEWARE = [
137 138
    'django_statsd.middleware.GraphiteRequestTimingMiddleware',
    'django_statsd.middleware.GraphiteMiddleware',
139
    'django.contrib.sessions.middleware.SessionMiddleware',
140 141 142 143 144 145

    # based on cookie or based on user agent. So people with Dutch browsers will see the Dutch version(?).
    # This project is going to be used in a variety of countries, with multiple languages, so auto-setting this
    # makes sense over having a fixed single option.
    # https://docs.djangoproject.com/en/2.0/topics/i18n/translation/#how-django-discovers-language-preference
    'django.middleware.locale.LocaleMiddleware',
146 147 148 149 150 151
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
152
    'django.contrib.admindocs.middleware.XViewMiddleware',  # admindocs
153 154
]

155 156 157 158 159
if DEBUG:
    # usage:
    # http://localhost:8000/data/vulnstats/NL/municipality/0?prof&count=100000&sort=cumtime
    MIDDLEWARE += ['django_cprofile_middleware.middleware.ProfilerMiddleware']

160
ROOT_URLCONF = 'failmap.urls'
161

162 163
# template needed for admin template
# this step is missing in the django jet tutorial, maybe because it's fairly common.
164

165 166 167
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
168 169 170
        'DIRS': [
            BASE_DIR + '/',
        ],
171 172 173
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
174
                'constance.context_processors.config',
175 176 177 178 179 180 181 182 183
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

184
WSGI_APPLICATION = 'failmap.wsgi.application'
185

186 187 188
# Assume traffic is proxied from frontend loadbalancers
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
189 190 191

# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
192
# hopefully fixes helpdesk issue https://github.com/django-helpdesk/django-helpdesk/issues/184
193
DATABASE_OPTIONS = {
Elger Jonker's avatar
Elger Jonker committed
194
    'mysql': {'init_command': "SET character_set_connection=utf8,"
195 196
                              "collation_connection=utf8_unicode_ci,"
                              "sql_mode='STRICT_ALL_TABLES';"},
197

198
}
Johan Bloemberg's avatar
Johan Bloemberg committed
199 200 201 202
DB_ENGINE = os.environ.get('DB_ENGINE', 'mysql')
DATABASE_ENGINES = {
    'mysql': 'failmap.app.backends.mysql',
}
203 204 205 206 207
DATABASES_SETTINGS = {
    # persisten local database used during development (runserver)
    'dev': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.environ.get('DB_NAME', 'db.sqlite3'),
Johan Bloemberg's avatar
Johan Bloemberg committed
208
    },
209 210 211 212 213 214 215
    # sqlite memory database for running tests without
    'test': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.environ.get('DB_NAME', 'db.sqlite3'),
    },
    # for production get database settings from environment (eg: docker)
    'production': {
Johan Bloemberg's avatar
Johan Bloemberg committed
216
        'ENGINE': DATABASE_ENGINES.get(DB_ENGINE, 'django.db.backends.' + DB_ENGINE),
217 218 219 220
        'NAME': os.environ.get('DB_NAME', 'failmap'),
        'USER': os.environ.get('DB_USER', 'failmap'),
        'PASSWORD': os.environ.get('DB_PASSWORD', 'failmap'),
        'HOST': os.environ.get('DB_HOST', 'mysql'),
221
        'OPTIONS': DATABASE_OPTIONS.get(os.environ.get('DB_ENGINE', 'mysql'), {})
222
    }
223
}
224 225 226
# allow database to be selected through environment variables
DATABASE = os.environ.get('DJANGO_DATABASE', 'dev')
DATABASES = {'default': DATABASES_SETTINGS[DATABASE]}
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

# Password validation
# https://docs.djangoproject.com/en/1.9/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/1.9/topics/i18n/

249 250 251 252 253
# Go to admin: language_code = language_code.replace('_', '-').lower()
# AttributeError: 'NoneType' object has no attribute 'replace'
# while settings are loaded and Django uses LANGUAGE_CODE as default. What overrides this?
# a possible undesired solution, http://source.mihelac.org/2009/11/12/django-set-language-for-admin/

254 255
# http://stackoverflow.com/questions/1832709/django-how-to-make-translation-work
# shoddy documentation on dashes and underscores... different than the "ll" suggestion.
256
# LANGUAGE_CODE = 'en-gb'
257
# Less text is better :) See: https://www.youtube.com/watch?v=0j74jcxSunY
258
LANGUAGES = (
259
    ('en', 'English'),
260
    ('nl', 'Dutch'),
261 262
    # This helps to find missing translations. Using this language the goal is to replace all text
    # strings with a single rainbow. In the end there should be no text, only rainbows! 🌈
263
    ('rainbowsandunicorns', '🌈'),
264 265
)

266
# There is no 🌈🦄 translation for humanize. Instead you'll get the english fallback values.
267 268
# language is now depending on the user agent.
# LANGUAGE_CODE = 'en'
269

270 271
LANGUAGE_COOKIE_NAME = 'language'

272 273 274 275
TIME_ZONE = 'UTC'

USE_I18N = True
USE_L10N = True
276

277 278 279 280
# Loaddata will show a massive amount of warnings, therefore use load-dataset. load-dataset will
# do exactly the same as loaddata, but will overwrite below flag preventing warnings.
USE_TZ = True

281 282 283
# https://docs.djangoproject.com/en/1.11/topics/i18n/translation/#how-django-discovers-translations
# In all cases the name of the directory containing the translation is expected to be named using
# locale name notation. E.g. de, pt_BR, es_AR, etc.
284
LOCALE_PATHS = ['locale']
285

286

287 288 289 290
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'
Johan Bloemberg's avatar
Johan Bloemberg committed
291

Johan Bloemberg's avatar
Johan Bloemberg committed
292
# Absolute path to aggregate to and serve static file from.
293 294 295
if DEBUG:
    STATIC_ROOT = 'static'
else:
296
    STATIC_ROOT = '/srv/failmap/static/'
Johan Bloemberg's avatar
Johan Bloemberg committed
297

298
TEST_RUNNER = 'failmap.testrunner.PytestTestRunner'
299

300
# From the Jet documentation, a different color for a different season.
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
JET_THEMES = [
    {
        'theme': 'default',  # theme folder name
        'color': '#47bac1',  # color of the theme's button in user menu
        'title': 'Default'  # theme title
    },
    {
        'theme': 'green',
        'color': '#44b78b',
        'title': 'Green'
    },
    {
        'theme': 'light-green',
        'color': '#2faa60',
        'title': 'Light Green'
    },
    {
        'theme': 'light-violet',
        'color': '#a464c4',
        'title': 'Light Violet'
    },
    {
        'theme': 'light-blue',
        'color': '#5EADDE',
        'title': 'Light Blue'
    },
    {
        'theme': 'light-gray',
        'color': '#222',
        'title': 'Light Gray'
    }
]
333

334 335
# see: https://github.com/geex-arts/django-jet/blob/
#   fea07040229d1b56800a7b8e6234e5f9419e2114/docs/config_file.rst
336
# required for custom modules
337 338 339 340 341 342 343
JET_APP_INDEX_DASHBOARD = 'failmap.app.dashboard.CustomAppIndexDashboard'

# Customize the Dashboard index page remove unneeded panels (eg: feeds) and add usefull stuff (actions).
JET_INDEX_DASHBOARD = 'failmap.app.dashboard.CustomIndexDashboard'

# expand menu items by default for quick access
JET_SIDE_MENU_COMPACT = True
344 345 346 347 348 349 350 351 352 353 354 355

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',  # sys.stdout
            'formatter': 'color',
        },
    },
    'formatters': {
        'debug': {
356 357
            'format': '%(asctime)s\t%(levelname)-8s - %(filename)-20s:%(lineno)-4s - '
                      '%(funcName)20s() - %(message)s',
358 359 360
        },
        'color': {
            '()': 'colorlog.ColoredFormatter',
361
            'format': '%(log_color)s%(asctime)s\t%(levelname)-8s - '
362
                      '%(message)s',
Johan Bloemberg's avatar
Johan Bloemberg committed
363
            'datefmt': '%Y-%m-%d %H:%M',
364
            'log_colors': {
365 366 367 368
                'DEBUG': 'green',
                'INFO': 'white',
                'WARNING': 'yellow',
                'ERROR': 'red',
369 370 371 372 373 374
                'CRITICAL': 'bold_red',
            },
        }
    },
    'loggers': {
        '': {
375
            'handlers': ['console'],  # used when there is no log defined or loaded.
376 377 378 379 380 381
            'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'),
        },
        'django': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
        },
382 383 384
    },
}

385 386 387 388
# Add a slash at the end so we know it's a directory. Tries to somewhat prevents doing things in root.
OUTPUT_DIR = os.environ.get('OUTPUT_DIR', os.path.abspath(os.path.dirname(__file__)) + '/')
VENDOR_DIR = os.environ.get('VENDOR_DIR', os.path.abspath(os.path.dirname(__file__) + '/../vendor/') + '/')

389 390 391 392
# the tools dir in this case are very small tools that build upon external dependencies, such as dnscheck.
# only use this if the vendor dir does not provide the needed command(s) in a simple way
TOOLS_DIR = os.environ.get('TOOLS_DIR', os.path.abspath(os.path.dirname(__file__) + '/../tools/') + '/')

393 394 395
# A number of tools and outputs are grouped to easier have access to all of them.
# Our vendor directory contains a number of small tools that are hard to install otherwise.

396
TOOLS = {
397
    # Chrome and firefox are special cases: they install very easily and therefore don't need further grouping.
398 399
    'chrome': {
        'executable': {
400 401 402 403 404
            # os.platform is used to see what binaries should be used on a worker.
            'Darwin': os.environ.get(
                'CHROME_EXECUTABLE_DARWIN', "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
            'Linux': os.environ.get(
                'CHROME_EXECUTABLE_LINUX', ""),
405
        },
406 407
        'screenshot_output_dir': OUTPUT_DIR + os.environ.get(
            'CHROME_SCREENSHOT_OUTPUT_DIR', 'map/static/images/screenshots/'),
408
    },
409
    # Chrome and firefox are special cases: they install very easily and therefore don't need further grouping.
410 411
    'firefox': {
        'executable': {
412 413 414 415 416
            # os.platform is used to see what binaries should be used on a worker.
            'Darwin': os.environ.get(
                'FIREFOX_EXECUTABLE_DARWIN', "/Applications/Firefox.app/Contents/MacOS/firefox"),
            'Linux': os.environ.get(
                'FIREFOX_EXECUTABLE_LINUX', ""),
417
        },
418 419
        'screenshot_output_dir': OUTPUT_DIR + os.environ.get(
            'FIREFOX_SCREENSHOT_OUTPUT_DIR', 'map/static/images/screenshots/'),
420
    },
421
    'theHarvester': {
422 423
        'executable': VENDOR_DIR + os.environ.get('THEHARVESTER_EXECUTABLE', "theHarvester/theHarvester.py"),
        'output_dir': OUTPUT_DIR + os.environ.get('THEHARVESTER_OUTPUT_DIR', "scanners/resources/output/theHarvester/"),
424 425
    },
    'dnsrecon': {
426 427 428 429 430
        'executable': VENDOR_DIR + os.environ.get('DNSRECON_EXECUTABLE', "dnsrecon/dnsrecon.py"),
        'output_dir': OUTPUT_DIR + os.environ.get('DNSRECON_OUTPUT_DIR', "scanners/resources/output/dnsrecon/"),

        # The most important wordlists are auto-generated by this software, and are thus output.
        'wordlist_dir': OUTPUT_DIR + os.environ.get('DNSRECON_WORDLIST_DIR', "scanners/resources/wordlists/"),
431
    },
432
    'openstreetmap': {
Elger Jonker's avatar
Elger Jonker committed
433 434
        'output_dir': OUTPUT_DIR + os.environ.get('OPENSTREETMAP_OUTPUT_DIR',
                                                  "scanners/resources/output/openstreetmap/"),
435
    },
436
    'sslscan': {
437 438
        # this is beta functionality and not supported in production
        # these are installed system wide and don't require a path (they might when development continues)
439 440 441 442
        'executable': {
            'Darwin': 'sslscan',
            'Linux': 'sslscan',
        },
443
        'report_output_dir': OUTPUT_DIR + "scanners/resources/output/sslscan/",
444 445
    },
    'openssl': {
446 447
        # this is beta functionality and not supported in production
        # these are installed system wide and don't require a path  (they might when development continues)
448 449 450 451 452 453
        'executable': {
            'Darwin': 'openssl',
            'Linux': 'openssl',
        },
    },
    'TLS': {
454
        # this is beta functionality and not supported in production
455 456 457 458 459
        'cve_2016_2107': VENDOR_DIR + 'CVE-2016-2107-padding-oracle/main.go',
        'cve_2016_9244': VENDOR_DIR + 'CVE-2016-9244-ticketbleed/ticketbleed.go',
        'cert_chain_resolver': {
            'Darwin': VENDOR_DIR + 'cert-chain-resolver/cert-chain-resolver-darwin',
            'Linux': VENDOR_DIR + 'cert-chain-resolver/cert-chain-resolver-linux',
460 461 462
        },
        'tls_check_output_dir': OUTPUT_DIR + os.environ.get('TLSCHECK_OUTPUT_DIR',
                                                            'scanners/resources/output/tls_check/'),
463 464 465
    },
    'dnscheck': {
        'executable': TOOLS_DIR + 'dnssec.pl'
466 467 468
    },
    'osaft': {
        'json': VENDOR_DIR + 'osaft/JSON-array.awk',
469
    }
470
}
471

472
# Compression
473 474 475
# Django-compressor is used to compress css and js files in production
# During development this is disabled as it does not provide any feature there
# Django-compressor configuration defaults take care of this.
476
# https://django-compressor.readthedocs.io/en/latest/usage/
477
# which plugins to use to find static files
478
STATICFILES_FINDERS = (
479
    # default static files finders
480 481 482 483 484
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # other finders..
    'compressor.finders.CompressorFinder',
)
485

486 487 488 489 490 491 492 493 494 495 496 497
COMPRESS_CSS_FILTERS = ['compressor.filters.cssmin.CSSCompressorFilter']

# Slimit doesn't work with vue. Tried two versions. Had to rewrite some other stuff.
# Now using the default, so not explicitly adding that to the settings
# COMPRESS_JS_FILTERS = ['compressor.filters.jsmin.JSMinFilter']

# Brotli compress storage gives some issues.
# This creates the original compressed and a gzipped compressed file.
COMPRESS_STORAGE = (
    'compressor.storage.GzipCompressorFileStorage'
)

498 499
# Disable caching during development and production.
# Django only emits caching headers, the webserver/caching-proxy makes sure the rest of the caching is handled.
Elger Jonker's avatar
Elger Jonker committed
500 501


502 503 504
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
505
    }
506
}
507

Johan Bloemberg's avatar
Johan Bloemberg committed
508 509 510 511 512
# Enable static file (js/css) compression when not running debug
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE
COMPRESS_OFFLINE = not DEBUG
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_ENABLED
# Enabled when debug is off by default.
513

514 515 516 517 518 519 520 521 522
# Celery 4.0 settings
# Pickle can work, but you need to use certificates to communicate (to verify the right origin)
# It's preferable not to use pickle, yet it's overly convenient as the normal serializer can not
# even serialize dicts.
# http://docs.celeryproject.org/en/latest/userguide/configuration.html
CELERY_accept_content = ['pickle', 'yaml']
CELERY_task_serializer = 'pickle'
CELERY_result_serializer = 'pickle'

523

524
# Celery config
525
CELERY_BROKER_URL = os.environ.get('BROKER', 'redis://localhost:6379/0')
526 527 528 529
ENABLE_UTC = True

# Any data transfered with pickle needs to be over tls... you can inject arbitrary objects with
# this stuff... message signing makes it a bit better, not perfect as it peels the onion.
530
# this stuff... message signing makes it a bit better, not perfect as it peels the onion.
531 532 533 534 535 536
# see: https://blog.nelhage.com/2011/03/exploiting-pickle/
# Yet pickle is the only convenient way of transporting objects without having to lean in all kinds
# of directions to get the job done. Intermediate tables to store results could be an option.
CELERY_ACCEPT_CONTENT = ['pickle']
CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_SERIALIZER = 'pickle'
537 538
CELERY_TIMEZONE = 'UTC'

Johan Bloemberg's avatar
Johan Bloemberg committed
539
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
Johan Bloemberg's avatar
Johan Bloemberg committed
540

541 542
CELERY_BROKER_CONNECTION_MAX_RETRIES = 1
CELERY_BROKER_CONNECTION_RETRY = False
543
CELERY_RESULT_EXPIRES = timedelta(hours=4)
544

Johan Bloemberg's avatar
Johan Bloemberg committed
545 546 547 548 549 550 551 552 553 554 555 556
# Use the value of 2 for celery prefetch multiplier. Previous was 1. The
# assumption is that 1 will block a worker thread until the current (rate
# limited) task is completed. When using 2 (or higher) the assumption is that
# celery will drop further rate limited task from the internal worker queue and
# fetch other tasks tasks that could be executed (spooling other rate limited
# tasks through in the process but to no hard except for a slight drop in
# overall throughput/performance). A to high value for the prefetch multiplier
# might result in high priority tasks not being picked up as Celery does not
# seem to do prioritisation in worker queues but only on the broker
# queues. The value of 2 is currently selected because it higher than 1,
# behaviour needs to be observed to decide if raising this results in
# further improvements without impacting the priority feature.
557
CELERY_WORKER_PREFETCH_MULTIPLIER = 2
558 559 560 561

# numer of tasks to be executed in parallel by celery
CELERY_WORKER_CONCURRENCY = 10

562 563 564 565 566 567
# Settings for statsd metrics collection. Statsd defaults over UDP port 8125.
# https://django-statsd.readthedocs.io/en/latest/#celery-signals-integration
STATSD_HOST = os.environ.get('STATSD_HOST', '127.0.0.1')
STATSD_PREFIX = 'failmap'
# register hooks for selery tasks
STATSD_CELERY_SIGNALS = True
568 569 570
# send database query metric (in production, in development we have debug toolbar for this)
if not DEBUG:
    STATSD_PATCHES = ['django_statsd.patches.db', ]
571 572 573

# enable some features during debug
if DEBUG:
574 575
    # enable debug toolbar if available
    try:
Johan Bloemberg's avatar
Johan Bloemberg committed
576
        import debug_toolbar
577

578
        INSTALLED_APPS.append('debug_toolbar')
Elger Jonker's avatar
Elger Jonker committed
579
        MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
580 581

        import debug_toolbar.settings
582

583
        DEBUG_TOOLBAR_PANELS = [
Elger Jonker's avatar
lint  
Elger Jonker committed
584 585 586 587
            'ddt_request_history.panels.request_history.RequestHistoryPanel',
        ] + debug_toolbar.settings.PANELS_DEFAULTS + [
            'django_statsd.panel.StatsdPanel',
        ]
588
        # send statsd metrics to debug_toolbar
589
        STATSD_CLIENT = 'django_statsd.clients.toolbar'
Johan Bloemberg's avatar
Johan Bloemberg committed
590
    except ImportError:
591
        pass
592

Johan Bloemberg's avatar
Johan Bloemberg committed
593
# if sentry DSN is provided register raven to emit events on exceptions
594 595
SENTRY_DSN = os.environ.get('SENTRY_DSN')
if SENTRY_DSN:
Johan Bloemberg's avatar
Johan Bloemberg committed
596 597
    INSTALLED_APPS += ('raven.contrib.django.raven_compat',)
    RAVEN_CONFIG = {
598
        'dsn': SENTRY_DSN,
Johan Bloemberg's avatar
Johan Bloemberg committed
599 600
        'release': __version__,
    }
601 602
    # add sentry ID to request for inclusion in templates
    # https://docs.sentry.io/clients/python/integrations/django/#message-references
Elger Jonker's avatar
Elger Jonker committed
603
    MIDDLEWARE.insert(0, 'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware')
Johan Bloemberg's avatar
Johan Bloemberg committed
604

Johan Bloemberg's avatar
Johan Bloemberg committed
605 606 607 608 609
    # Celery specific handlers
    client = raven.Client(SENTRY_DSN)
    raven.contrib.celery.register_logger_signal(client)
    raven.contrib.celery.register_signal(client)

Johan Bloemberg's avatar
Johan Bloemberg committed
610
# set javascript sentry token if provided
611
SENTRY_TOKEN = os.environ.get('SENTRY_TOKEN', '')
612 613 614 615

SENTRY_ORGANIZATION = 'internet-cleanup-foundation'
SENTRY_PROJECT = 'faalkaart'
SENTRY_PROJECT_URL = 'https://sentry.io/%s/%s' % (SENTRY_ORGANIZATION, SENTRY_PROJECT)
616 617 618 619 620 621 622

# Some workers or (development) environments don't support both IP networks
# Note that not supporting either protocols can result in all endpoints being killed as they are unreachable by scanners
# We don't check these settings anywhere for sanity as some workers might not need a network at all.
# The defaults stem from our live environment, where we've set IPv4 being present on all containers and workers.
NETWORK_SUPPORTS_IPV4 = os.environ.get('NETWORK_SUPPORTS_IPV4', True)
NETWORK_SUPPORTS_IPV6 = os.environ.get('NETWORK_SUPPORTS_IPV6', False)
623 624 625

# atomic imports: fail completely, not half
IMPORT_EXPORT_USE_TRANSACTIONS = True
626

627 628
#########
# Begin constance settigns
629
# runtime configuration from database
630 631 632
# https://django-constance.readthedocs.io/en/latest/
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'

Elger Jonker's avatar
Elger Jonker committed
633 634 635 636 637 638 639 640

CONSTANCE_ADDITIONAL_FIELDS = {
    'yes_no_null_select': ['django.forms.fields.ChoiceField', {
        'widget': 'django.forms.Select',
        'choices': ((None, "-----"), ("1", "Yes"), ("0", "No"))
    }],
}

Elger Jonker's avatar
Elger Jonker committed
641

642
CONSTANCE_CONFIG = {
Elger Jonker's avatar
Elger Jonker committed
643
    'COMMENTS': ('', 'Some comments by you that say a little bit about why below settings are the way they are.', str),
644 645

    'PROJECT_NAME': ('', 'The name of this mapping project, used for branding and promotion.', str),
646
    'PROJECT_COUNTRY': ('NL', 'Two letter ISO code of the country that should be shown.', str),
Elger Jonker's avatar
Elger Jonker committed
647
    'PROJECT_TAGLINE': ('', 'Tagline for this project.', str),
648 649 650 651 652 653 654 655
    'PROJECT_WEBSITE': ('', 'The url where this site is located.', str),
    'PROJECT_MAIL': ('', 'The address where people can contact for more info about this project.', str),
    'PROJECT_ISSUE_MAIL': ('', 'The address where people can mail when they encounter issues, for example when they '
                               'are using the incorrect findings button.', str),
    'PROJECT_TWITTER': ('', 'The twitter address where people can follow this project. Include the @!', str),
    'PROJECT_FACEBOOK': ('', 'The facebook address where people can follow this project. Has to be a complete url.',
                         str),

656 657 658 659

    'GOOGLE_MAPS_API_KEY': ('AIzaSyBXJbEUxGW1dAB4hJOlmKdYelfoRY6_fjo',
                            'API Key of google maps that can be used in the game / adding section.', str),

660 661 662
    'MAPBOX_ACCESS_TOKEN': ('pk.eyJ1IjoibXJmYWlsIiwiYSI6ImNqMHRlNXloczAwMWQyd3FxY3JkMnUxb3EifQ.9nJBaedxrry91O1d90wfuw',
                            'Access token for Mapbox', str),

663 664
    'WAMBACHERS_OSM_CLIKEY': ('', 'CLI key for Wambachers OSM export feature', str),

665 666 667 668 669 670 671 672 673
    'RESPONSIBLE_ORGANIZATION_NAME': ('', 'The name of the organization running this project.', str),
    'RESPONSIBLE_ORGANIZATION_PROMO_TEXT': ('', 'Some text promoting this organization and it\s mission. This text will'
                                                ' not be translated.', str),
    'RESPONSIBLE_ORGANIZATION_WEBSITE': ('', 'The name of the organization running this project.', str),
    'RESPONSIBLE_ORGANIZATION_MAIL': ('', 'The name of the organization running this project.', str),
    'RESPONSIBLE_ORGANIZATION_TWITTER': ('', 'The twitter address where people can follow this project. Include '
                                             'the @!', str),
    'RESPONSIBLE_ORGANIZATION_FACEBOOK': ('', 'The facebook address where people can follow this project. Make sure'
                                              ' this is a complete url.', str),
Elger Jonker's avatar
Elger Jonker committed
674 675 676
    'RESPONSIBLE_ORGANIZATION_LINKEDIN': ('', 'Linkedin page url.', str),
    'RESPONSIBLE_ORGANIZATION_WHATSAPP': ('', 'Whatsapp number.', str),
    'RESPONSIBLE_ORGANIZATION_PHONE': ('', 'Phone number, displayed as a sip:// addres.', str),
677

Elger Jonker's avatar
Elger Jonker committed
678
    'SHOW_INTRO': (True, 'Shows the standard introduction.', bool),
679
    'SHOW_GOOD_BAD': (True, 'Shows the good / bad lists.', bool),
Elger Jonker's avatar
Elger Jonker committed
680 681 682 683 684 685 686 687 688 689 690 691 692
    'SHOW_EXTENSIVE_STATISTICS': (True, 'Shows extended statistics.', bool),
    'SHOW_STATS_GRAPHS': (True, 'Shows graphs in extended statistics. '
                                'Extended statistics needs to be enabled for this to have effect.', bool),
    'SHOW_STATS_IMPROVEMENTS': (True, 'Shows improvements in extended statistics. '
                                      'Extended statistics needs to be enabled for this to have effect.', bool),
    'SHOW_STATS_NUMBERS': (True, 'Shows numbers in extended statistics. '
                                 'Extended statistics needs to be enabled for this to have effect.', bool),
    'SHOW_STATS_CHANGES': (True, 'Shows changes in extended statistics. '
                                 'Extended statistics needs to be enabled for this to have effect.', bool),
    'SHOW_DATASETS': (True, 'Shows dataset downloads. Note: dataset downloads are always available, even if they '
                            'are not shown on the website.', bool),
    'SHOW_TICKER': (False, 'Shows stock-ticker with updates in the past month.', bool),

Elger Jonker's avatar
Elger Jonker committed
693
    'SHOW_SERVICES': (True, 'Show table with how many services are scanned. Requires SHOW_STATS_NUMBERS.', bool),
Elger Jonker's avatar
Elger Jonker committed
694 695 696 697 698 699 700
    'SHOW_DNS_DNSSEC': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
    'SHOW_HTTP_TLS_QUALYS': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
    'SHOW_HTTP_MISSING_TLS': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
    'SHOW_HTTP_HEADERS_HSTS': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
    'SHOW_HTTP_HEADERS_XFO': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
    'SHOW_HTTP_HEADERS_X_XSS': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
    'SHOW_HTTP_HEADERS_X_CONTENT': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
Elger Jonker's avatar
Elger Jonker committed
701
    'SHOW_FTP': (True, 'Show graphs/stats of this? May cause empty spots on the site.', bool),
Elger Jonker's avatar
Elger Jonker committed
702 703 704 705 706 707 708 709 710 711 712 713

    # todo: schedule this once per week by default.
    'DISCOVER_URLS_USING_NSEC': (True, 'Discover new domains using DNSSEC NSEC1 hashes? (See docs)', bool),
    'DISCOVER_URLS_USING_KNOWN_SUBDOMAINS': (True, 'Discover new domains using known subdomains? (See docs)', bool),
    'DISCOVER_URLS_USING_CERTIFICATE_TRANSPARENCY': (True, 'Discover new domains using crt.sh '
                                                           'certificate transperancy database? (See docs)', bool),
    'DISCOVER_HTTP_ENDPOINTS': (True, 'Do you want to discover HTTP endpoints?', bool),

    'SCAN_AT_ALL': (True, 'Do you want to scan at all?', bool),
    'SCAN_DNS_DNSSEC': (True, 'Do you want to scan for DNSSEC issues?', bool),
    'SCAN_HTTP_TLS_QUALYS': (True, 'Do you want to scan for TLS issues through Qualys? This is about 1 scan per '
                                   'two minutes. Cloud scanning can improve this a bit.', bool),
714 715
    'SCAN_HTTP_TLS_OSAFT': (True, 'Experimental: Do you want to scan for TLS issues through OSaft? This is about '
                                  '3 scans per minute. Cloud scanning can improve this a bit.', bool),
Elger Jonker's avatar
Elger Jonker committed
716 717 718 719 720 721
    'SCAN_HTTP_MISSING_TLS': (True, 'Do you want to scan for endpoints that don\'t have a secure counterpart?', bool),
    'SCAN_HTTP_HEADERS_HSTS': (True, 'Do you want to scan for missing '
                                     'Hypertext Strict Transport Security headers?', bool),
    'SCAN_HTTP_HEADERS_XFO': (True, 'Do you want to scan for missing X-Frame-Options headers?', bool),
    'SCAN_HTTP_HEADERS_X_XSS': (True, 'Do you want to scan for missing X-XSS headers?', bool),
    'SCAN_HTTP_HEADERS_X_CONTENT': (True, 'Do you want to scan for missing X-Content-Type issues?', bool),
Elger Jonker's avatar
Elger Jonker committed
722
    'SCAN_FTP': (True, 'Do you want to scan for FTP servers that are missing encryption?', bool),
Elger Jonker's avatar
Elger Jonker committed
723 724 725 726
    'CREATE_HTTP_SCREENSHOT': (True, 'Todo: Does not work yet! Do you want to create screenshots for HTTP endpoints?',
                               bool),

    # future: FTP, TLS_QUICK (way less robust and complete, much faster)
Elger Jonker's avatar
Elger Jonker committed
727
    'REPORT_INCLUDE_FTP': (True, 'Do you want to add FTP encryption issues to the report?', bool),
Elger Jonker's avatar
Elger Jonker committed
728 729 730 731 732 733 734 735
    'REPORT_INCLUDE_DNS_DNSSEC': (True, 'Do you want to add DNSSEC issues to the report?', bool),
    'REPORT_INCLUDE_HTTP_TLS_QUALYS': (True, 'Do you want to show TLS results in the report?', bool),
    'REPORT_INCLUDE_HTTP_MISSING_TLS': (True, 'Do you want to show missing TLS in the report?', bool),
    'REPORT_INCLUDE_HTTP_HEADERS_HSTS': (True, 'Do you want to HSTS in the report?', bool),
    'REPORT_INCLUDE_HTTP_HEADERS_XFO': (True, 'Do you want to show XFO in the report?', bool),
    'REPORT_INCLUDE_HTTP_HEADERS_X_XSS': (True, 'Do you want to show X-XSS protection headers in the report?', bool),
    'REPORT_INCLUDE_HTTP_HEADERS_X_CONTENT': (True, 'Do you want to show X-Content-Type headers in the report?', bool),

Elger Jonker's avatar
Elger Jonker committed
736 737 738 739 740 741 742
    # scanning pre-requisites
    'CONNECTIVITY_TEST_DOMAIN': ('faalkaart.nl', 'A server that is reachable over IPv4. This is used by a worker '
                                                 'to determine what kind of scans it can do. Enter an '
                                                 'address that you own or manage.', str),
    'IPV6_TEST_DOMAIN': ('faalkaart.nl', 'A server that is reachable over IPv6. This is used by a worker to determine '
                                         'what kind of scans it can do. Enter an address that you own or manage.', str),

Elger Jonker's avatar
Elger Jonker committed
743 744
    'GITTER_CHAT_ENABLE': (False, 'Show the Gitter Chat option on the website (using gitter sidecar).', bool),
    'GITTER_CHAT_CHANNEL': ('internet-cleanup-foundation/support', 'Name of the channel chat takes place.', str),
Elger Jonker's avatar
Elger Jonker committed
745

Elger Jonker's avatar
Elger Jonker committed
746 747 748 749
    #
    # 'USE_CUSTOM_INTRO': (False, 'If you want to use an (untranslated) custom intro, enable this. Enabling this'
    #                             'will remove the standard intro and has several fields that can be filled with '
    #                             'custom HTML.', bool),
750
}
751

Elger Jonker's avatar
Elger Jonker committed
752
CONSTANCE_CONFIG_FIELDSETS = OrderedDict([
753
    ('General', ('COMMENTS', 'MAPBOX_ACCESS_TOKEN', 'WAMBACHERS_OSM_CLIKEY')),
754

755 756
    ('Project', ('PROJECT_NAME', 'PROJECT_COUNTRY', 'PROJECT_TAGLINE', 'PROJECT_WEBSITE', 'PROJECT_MAIL',
                 'PROJECT_ISSUE_MAIL', 'PROJECT_TWITTER', 'PROJECT_FACEBOOK')),
757

Elger Jonker's avatar
Elger Jonker committed
758 759 760 761 762
    ('Responsible', ('RESPONSIBLE_ORGANIZATION_NAME', 'RESPONSIBLE_ORGANIZATION_PROMO_TEXT',
                     'RESPONSIBLE_ORGANIZATION_WEBSITE', 'RESPONSIBLE_ORGANIZATION_MAIL',
                     'RESPONSIBLE_ORGANIZATION_TWITTER', 'RESPONSIBLE_ORGANIZATION_FACEBOOK',
                     'RESPONSIBLE_ORGANIZATION_LINKEDIN', 'RESPONSIBLE_ORGANIZATION_WHATSAPP',
                     'RESPONSIBLE_ORGANIZATION_PHONE')),
763

Elger Jonker's avatar
Elger Jonker committed
764 765 766 767
    ('Website', ('SHOW_INTRO', 'SHOW_GOOD_BAD', 'SHOW_EXTENSIVE_STATISTICS', 'SHOW_DATASETS', 'SHOW_STATS_GRAPHS',
                 'SHOW_STATS_IMPROVEMENTS', 'SHOW_STATS_NUMBERS', 'SHOW_SERVICES', 'SHOW_STATS_CHANGES', 'SHOW_TICKER',
                 'SHOW_DNS_DNSSEC', 'SHOW_HTTP_TLS_QUALYS', 'SHOW_HTTP_MISSING_TLS',
                 'SHOW_HTTP_HEADERS_HSTS', 'SHOW_HTTP_HEADERS_XFO', 'SHOW_HTTP_HEADERS_X_XSS',
Elger Jonker's avatar
Elger Jonker committed
768
                 'SHOW_HTTP_HEADERS_X_CONTENT', 'SHOW_FTP'
Elger Jonker's avatar
Elger Jonker committed
769
                 )),
Elger Jonker's avatar
Elger Jonker committed
770

Elger Jonker's avatar
Elger Jonker committed
771 772
    ('Discovery', ('DISCOVER_URLS_USING_NSEC', 'DISCOVER_URLS_USING_KNOWN_SUBDOMAINS',
                   'DISCOVER_URLS_USING_CERTIFICATE_TRANSPARENCY', 'DISCOVER_HTTP_ENDPOINTS')),
Elger Jonker's avatar
Elger Jonker committed
773

Elger Jonker's avatar
Elger Jonker committed
774
    ('Scanner Capabilities', ('CONNECTIVITY_TEST_DOMAIN', 'IPV6_TEST_DOMAIN')),
Elger Jonker's avatar
Elger Jonker committed
775

776 777
    ('Scanning', ('SCAN_AT_ALL', 'SCAN_DNS_DNSSEC', 'SCAN_HTTP_TLS_QUALYS', 'SCAN_HTTP_TLS_OSAFT',
                  'SCAN_HTTP_MISSING_TLS', 'SCAN_HTTP_HEADERS_HSTS',
Elger Jonker's avatar
Elger Jonker committed
778
                  'SCAN_HTTP_HEADERS_XFO', 'SCAN_HTTP_HEADERS_X_XSS', 'SCAN_HTTP_HEADERS_X_CONTENT', 'SCAN_FTP',
Elger Jonker's avatar
Elger Jonker committed
779
                  'CREATE_HTTP_SCREENSHOT')),
Elger Jonker's avatar
Elger Jonker committed
780

Elger Jonker's avatar
Elger Jonker committed
781 782 783
    ('Reporting', ('REPORT_INCLUDE_DNS_DNSSEC', 'REPORT_INCLUDE_HTTP_TLS_QUALYS', 'REPORT_INCLUDE_HTTP_MISSING_TLS',
                   'REPORT_INCLUDE_HTTP_HEADERS_HSTS',
                   'REPORT_INCLUDE_HTTP_HEADERS_XFO', 'REPORT_INCLUDE_HTTP_HEADERS_X_XSS',
Elger Jonker's avatar
Elger Jonker committed
784
                   'REPORT_INCLUDE_HTTP_HEADERS_X_CONTENT', 'REPORT_INCLUDE_FTP')),
785 786 787

    ('Game', ('GOOGLE_MAPS_API_KEY',)),

Elger Jonker's avatar
Elger Jonker committed
788
    ('Chat (using gitter)', ('GITTER_CHAT_ENABLE', 'GITTER_CHAT_CHANNEL'))
Elger Jonker's avatar
Elger Jonker committed
789
])
Elger Jonker's avatar
Elger Jonker committed
790 791 792 793 794 795 796 797 798

# Check for constance configuration issues:
# See also: https://github.com/jazzband/django-constance/issues/293
variables_in_fieldsets = [i for sub in [CONSTANCE_CONFIG_FIELDSETS[x] for x in CONSTANCE_CONFIG_FIELDSETS] for i in sub]
variables_in_config = [x for x in CONSTANCE_CONFIG]
missing = set(variables_in_config) - set(variables_in_fieldsets)
if missing:
    raise EnvironmentError("Constance config variables %s are missing in constance config fieldsets." % missing)

799 800
# End constance settings
########
801

802
# https://docs.djangoproject.com/en/1.11/ref/settings/#data-upload-max-number-fields
803 804 805
# The default is far too low with various inlines (even on the test dataset).
# Yes, we happily exceed 1000 fields anyday. No problem :)
DATA_UPLOAD_MAX_NUMBER_FIELDS = 4242
Johan Bloemberg's avatar
Johan Bloemberg committed
806

807 808
########
# Begin game settings:
Johan Bloemberg's avatar
Johan Bloemberg committed
809 810
# login on the frontpage should redirect to the game landingpage
LOGIN_REDIRECT_URL = '/game/'
811 812
LOGIN_URL = '/authentication/login/'
LOGOUT_REDIRECT_URL = '/'
813

Elger Jonker's avatar
Elger Jonker committed
814
CRISPY_TEMPLATE_PACK = 'bootstrap3'
815

816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
# End game settigns
#######

#######
# Begin helpdesk settings:
# Unfortunately we cannot manage these settings with constance. And therefore you should be still editing
# this file. We're sorry.
SITE_ID = 1  # For django-helpdesk. We only run one site...

# helps against spam, will leak all your data, so be careful. Spam could be protected against on your mailserver...
AKISMET_API_KEY = os.environ.get('AKISMET_API_KEY', '')
TYPEPAD_ANTISPAM_API_KEY = os.environ.get('TYPEPAD_ANTISPAM_API_KEY', '')

# If you use another server for sending mail, see config example here:
# http://django-helpdesk.readthedocs.io/en/0.2.x/configuration.html
# EMAIL_HOST = 'XXXXX'
# EMAIL_HOST_USER = '[email protected]'
# EMAIL_HOST_PASSWORD = '123456'
# Make sure the MEDIA_ROOT is NOT readable from the webserver directly. So no https://bla/media.
MEDIA_ROOT = os.environ.get('MEDIA_ROOT', os.path.abspath(os.path.dirname(__file__)) + '/../')

# End of helpdesk settings
Elger Jonker's avatar
Elger Jonker committed
838 839 840 841
#######


#######
Elger Jonker's avatar
Elger Jonker committed
842
# begin django jet menu configuration
Elger Jonker's avatar
Elger Jonker committed
843 844 845 846 847 848 849 850
# This helps making various resources and fewer used features less visible.


# todo: add permissions: 'permissions': ['core.user']

# The following items are hidden on purpose:
# core.site (we only have one site)
# scanners.state, will be deprecated and removed (if not already)
Elger Jonker's avatar
Elger Jonker committed
851
# See: http://jet.readthedocs.io/en/latest/config_file.html#custom-menu
Elger Jonker's avatar
Elger Jonker committed
852

Elger Jonker's avatar
Elger Jonker committed
853
JET_SIDE_MENU_ITEMS = [  # A list of application or custom item dicts
Elger Jonker's avatar
Elger Jonker committed
854 855

    {'label': _('🔧 configuration'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
856 857
        {'name': 'auth.user'},
        {'name': 'auth.group'},
Elger Jonker's avatar
Elger Jonker committed
858 859
        {'name': 'constance.config', 'label': _('configuration')},
        {'name': 'map.configuration', 'label': _('map configuration')},
Elger Jonker's avatar
Elger Jonker committed
860 861 862
        {'name': 'map.administrativeregion', 'label': _('import regions')},
    ]},

Elger Jonker's avatar
Elger Jonker committed
863
    {'app_label': 'organizations', 'label': _('🏢 organizations'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
864 865 866 867 868 869 870
        {'name': 'organization'},
        {'name': 'url'},
        {'name': 'promise'},
        {'name': 'coordinate'},
        {'name': 'organizationtype'},
    ]},

Elger Jonker's avatar
Elger Jonker committed
871
    {'app_label': 'scanners', 'label': _('🔬 scanners'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
872 873
        {'name': 'endpoint'},
        {'name': 'endpointgenericscan'},
874
        {'name': 'tlsscan'},
Elger Jonker's avatar
Elger Jonker committed
875 876 877 878 879 880 881
        {'name': 'tlsqualysscan'},
        {'name': 'urlgenericscan'},
        {'name': 'screenshot'},
        {'name': 'urlip'},
        {'name': 'endpointgenericscanscratchpad'},
    ]},

Elger Jonker's avatar
Elger Jonker committed
882 883 884 885 886 887
    {'label': _('🗺️ map (autogenerated)'), 'items': [
        {'name': 'map.organizationrating'},
        {'name': 'map.urlrating'},
    ]},

    {'label': _('🕒 periodic tasks'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
888 889 890 891 892 893 894
        {'name': 'app.job'},
        {'name': 'django_celery_beat.periodictask'},
        {'name': 'django_celery_beat.crontabschedule'},
        {'name': 'django_celery_beat.intervalschedule'},
        {'name': 'django_celery_beat.solarschedule'},
    ]},

Elger Jonker's avatar
Elger Jonker committed
895
    {'app_label': 'helpdesk', 'label': _('ℹ️ helpdesk'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
896 897 898 899 900 901 902 903 904 905 906 907
        {'name': 'queue'},
        {'name': 'ticket'},
        {'name': 'followup'},
        {'name': 'customfield'},
        {'name': 'presetreply'},
        {'name': 'emailtemplate'},
        {'name': 'escalationexclusion'},
        {'name': 'ignoreemail'},
        {'name': 'kbcategory'},
        {'name': 'kbitem'},
    ]},

Elger Jonker's avatar
Elger Jonker committed
908
    {'app_label': 'hypersh', 'label': _('☁️ hypersh cloud scans'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
909 910 911 912 913 914
        {'name': 'containerenvironment'},
        {'name': 'containerconfiguration'},
        {'name': 'containergroup'},
        {'name': 'credential'},
    ]},

Elger Jonker's avatar
Elger Jonker committed
915
    {'app_label': 'game', 'label': _('👾️ the game'), 'items': [
Elger Jonker's avatar
Elger Jonker committed
916 917 918
        {'name': 'contest'},
        {'name': 'team'},
        {'name': 'organizationsubmission'},
919 920 921
        {'label': _('New organizations'),
         'url': '/admin/game/organizationsubmission/?has_been_accepted__exact=0&has_been_rejected__exact=0&o=-5',
         'url_blank': False},
Elger Jonker's avatar
Elger Jonker committed
922
        {'name': 'urlsubmission'},
923 924 925
        {'label': _('New urls'),
         'url': '/admin/game/urlsubmission/?has_been_accepted__exact=0&has_been_rejected__exact=0&o=-6.2.3',
         'url_blank': False},
Elger Jonker's avatar
Elger Jonker committed
926 927
    ]},
]
Elger Jonker's avatar
Elger Jonker committed
928 929
# end django jet menu configuration
########
930 931 932

########
# Begin Cacheops
933 934 935
#         # django cacheops doesn't work with raw.
#         # too bad https://github.com/Suor/django-cacheops
#         # it's the elephant in the room in the documentation: all are explained except this one.
936 937 938 939

# Cacheops has been added to improve the retrieval of graphs-queries. At the time of writing it's only in use
# there using a hack to improve querying speed.

Elger Jonker's avatar
Elger Jonker committed
940 941 942
# It was not an option to rewrite queries to tailor to specific caching schemes per database vendor, django ORM also
# does not support that.

943 944 945 946 947 948 949 950 951 952 953 954
# It's a hack because out of the box cacheops doesn't support raw querysets (the only caveat without explanation).
# But we just need the list of data for displaying, thus we can wrap that in a function and use function result caching
#
# Note that lru_cache from functools does not support lists or complex types, while cahcheops does.
#
# I've chosen cacheops because it's actively maintained and has a lot of commits, while it's backlog is clean.
# Another reason is that it doesn't affect anything, except what you explicitly cache. So behaviour of the rest of the
# application is unchanged.

# If redis is not available, that is not a problem. For example: certain development scenario's or when redis fails.
# in that case a limited set of functions are performed without caching (and thus slower) but without crashes.
# If it's too slow, the webserver will kill it anyway, or in dev environments it will take longer.
955 956 957 958 959 960 961 962 963 964 965
# CACHEOPS_DEGRADE_ON_FAILURE = True

# CACHEOPS_REDIS = {
#     'host': 'localhost',  # redis-server is on same machine
#     'port': 6379,        # default redis port
#     'db': 1,             # SELECT non-default redis database
#                          # using separate redis db or redis instance
#                          # is highly recommended
#
#     'socket_timeout': 3,   # connection timeout in seconds, optional
# }
966 967
# End cacheops
########