""" Django settings for console project. """ import os import sys from celery.schedules import crontab from django.utils.translation import gettext_lazy from console.services.product import load_product_version # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) DEBUG = int(os.environ.get('DEBUG', '0')) > 0 # Program is started under testing framework TEST_MODE = 'test' in sys.argv or 'pytest' in sys.modules or os.environ.get("TEST_MODE") # Program is used by developer (human), i.e. loads additional debug software DEV_MODE = DEBUG and not TEST_MODE # False to disable access to admin control panel via web ADMIN_PANEL_ENABLED = DEV_MODE ################################## ### SECURITY ### ################################## CORS_ALLOW_ALL_ORIGINS = True CORS_ALLOW_CREDENTIALS = True CORS_EXPOSE_HEADERS = ['Content-Disposition'] ALLOWED_HOSTS = ['*'] ###################################### ### APPLICATIONS ### ###################################### INSTALLED_APPS = [ 'django.forms', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'django_json_widget', 'solo', 'django_celery_beat', 'sequences.apps.SequencesConfig', 'corsheaders', 'django_filters', 'channels', ] PROJECT_APPS = [ 'assets.apps.AssetsConfig', 'license_info.apps.LicenseInfoConfig', 'perms.apps.PermsConfig', 'console.apps.ConsoleConfig', 'core.apps.CoreConfig', 'correlation.apps.CorrelationConfig', 'dashboard.apps.DashboardConfig', 'company.apps.CompanyConfig', 'ncircc.apps.NcirccConfig', 'logstash.apps.LogstashConfig', 'networkmap.apps.NetworkmapConfig', 'users.apps.UsersConfig', 'incident_export.apps.IncidentExportConfig', 'storage.apps.StorageConfig', 'incident.apps.IncidentConfig', 'events.apps.EventsConfig', 'rotation.apps.RotationConfig', 'inputs.apps.InputsConfig', 'devices.apps.DevicesConfig', 'notifications.apps.NotificationsConfig', ] INSTALLED_APPS += PROJECT_APPS MIDDLEWARE = [ 'core.middleware.LicenseMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'core.middleware.TimezoneMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ######################################## ### AUTHENTICATION ### ######################################## AUTHENTICATION_BACKENDS = [ 'core.backends.ConsoleAuthBackend.ConsoleAuthSystem', 'django.contrib.auth.backends.ModelBackend', ] AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': { 'min_length': 8, } }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] ################################## ### DATABASE ### ################################## if not os.environ['POSTGRES_PORT']: os.environ['POSTGRES_PORT'] = '5432' DATABASES = { 'default': { 'ENGINE': "django.db.backends.postgresql", # Project depends on postgre, so no way to change it from env 'NAME': os.environ.get('POSTGRES_DB'), 'USER': os.environ.get('POSTGRES_USER'), 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), 'HOST': os.environ.get('POSTGRES_HOST'), 'PORT': os.environ.get('POSTGRES_PORT'), } } DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' ################################# ### LOGGING ### ################################# LOG_PATH = os.environ.get('LOG_PATH', os.path.join(BASE_DIR, 'dockerlogs')) USER_LOG_FILENAME = os.environ.get('USER_LOG_FILENAME', 'console.log') MIN_LOG_LEVEL = os.environ.get('MIN_LOG_LEVEL', 'DEBUG') LOG_MAX_BYTES = int(os.environ.get('LOG_MAX_BYTES', 1024 * 1024 * 5)) LOG_BACKUP_COUNT = int(os.environ.get('LOG_BACKUP_COUNT', 500)) os.makedirs(LOG_PATH, exist_ok=True) LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'info_message': { 'format': '%(asctime)s %(levelname)s %(message)s', }, 'debug_format': { 'format': '%(asctime)s %(levelname)s %(filename)s %(funcName)s %(message)s' } }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'level': MIN_LOG_LEVEL, }, 'file': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', 'filename': os.path.join(LOG_PATH, USER_LOG_FILENAME), 'formatter': 'info_message', 'encoding': 'utf-8', 'maxBytes': LOG_MAX_BYTES, 'backupCount': LOG_BACKUP_COUNT, }, }, 'loggers': { '': { 'handlers': ['file', 'console'], 'level': MIN_LOG_LEVEL, }, }, } ############################################## ### INTERNATIONALIZATION ### ############################################## LANGUAGE_CODE = 'en' LANGUAGES = [ ('en', gettext_lazy('English')), ('ru', gettext_lazy('Russian')), ] INITIAL_DATE_FORMAT = "Y-m-d" # @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones TIME_ZONE = os.environ.get('TIME_ZONE', 'UTC') # Timezone used for users by default DEFAULT_CURRENT_TIMEZONE = os.environ.get('DEFAULT_CURRENT_TIMEZONE', 'Europe/Moscow') USE_I18N = True USE_L10N = True USE_TZ = True LOCALE_PATHS = [ os.path.join(BASE_DIR, 'locale') ] ############################### ### FILES ### ############################### # Build paths for generated files like static inside the project like this: os.path.join(PUBLIC_DIR, ...) PUBLIC_DIR = os.environ.get('PUBLIC_DIR', os.path.join(BASE_DIR, 'public')) PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) STATIC_URL = '/static/' MEDIA_URL = '/media/' STATIC_ROOT = os.path.join(PUBLIC_DIR, 'static') MEDIA_ROOT = os.path.join(PUBLIC_DIR, 'media') REDIS_HOST = os.environ.get('REDIS_HOST', 'redis') REDIS_PORT = int(os.environ.get('REDIS_PORT', 6379)) REDIS_CACHE_TIMEOUT = 86400 ############################### ### CACHE ### ############################### SOLO_CACHE = 'local' SOLO_CACHE_TIMEOUT = 60 * 5 # 5 mins SOLO_CACHE_PREFIX = 'solo' CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', }, 'local': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', }, 'redis': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': f'redis://{REDIS_HOST}:{REDIS_PORT}/1', 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient' } } } ############################# ### DRF ### ############################# REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ), 'DEFAULT_FILTER_BACKENDS': ( 'django_filters.rest_framework.DjangoFilterBackend', 'rest_framework.filters.OrderingFilter', 'core.backends.filters.SearchAllFieldsBackend', ), 'DEFAULT_PAGINATION_CLASS': 'core.services.pagination.BasicPagination', 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ], } ################################ ### CELERY ### ################################ CELERY_BROKER_URL = f'redis://{REDIS_HOST}:{REDIS_PORT}' CELERY_RESULT_BACKEND = f'redis://{REDIS_HOST}:{REDIS_PORT}' CELERY_ACCEPT_CONTENT = ['application/json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_TIMEZONE = TIME_ZONE CELERY_IMPORTS = ['devices.tasks.firewall', 'devices.tasks.sensor'] """ Single place to setup at which time daily tasks should execute, crontab schedule object""" DAILY_CRONTAB = crontab(minute='0', hour='1') """ Single place to setup at which time weekly tasks should execute, crontab schedule object""" WEEKLY_CRONTAB = crontab(minute='0', hour='1', day_of_week='1') """ Single place to setup at which time monthly tasks should execute, crontab schedule object""" MONTHLY_CRONTAB = crontab(minute='0', hour='1', day_of_month='1') """ Execute every 2 minutes.""" EVERY_2_MINUTE = crontab(minute='*/2') ROTATE_SIZE_CHECK_CRONTAB = crontab(minute='*/5') CELERY_BEAT_SCHEDULE = { 'update_statistics': { 'task': 'dashboard.tasks.update_statistics_task', 'schedule': crontab() }, 'expire_users': { 'task': 'console.tasks.expire_users_task', 'schedule': DAILY_CRONTAB }, 'update_auto_network_map_data': { 'task': 'networkmap.tasks.update_auto_network_map_data', 'schedule': crontab() }, 'update_firewall_info_task': { 'task': 'devices.tasks.firewall.update_firewall_info_task', 'schedule': crontab() }, 'update_amount_of_elk_events': { 'task': 'console.tasks.update_amount_of_aggregated_events', 'schedule': crontab() }, 'check_blocked_users': { 'task': 'core.tasks.check_blocked_users', 'schedule': crontab() }, 'update_status_notification': { 'task': 'ncircc.tasks.update_status_notification', 'schedule': crontab(), # todo Уточнить точное время }, 'update_comments': { 'task': 'ncircc.tasks.update_comments', 'schedule': crontab(), # todo Уточнить точное время }, 'ping_sensors': { 'task': 'devices.tasks.sensor.ping_sensors', 'schedule': crontab() }, 'get_disk_usage_task': { 'task': 'core.tasks.get_disk_usage_task', 'schedule': crontab() }, 'reboot_correlator_task': { 'task': 'correlation.tasks.reboot_correlator_task', 'schedule': EVERY_2_MINUTE, }, } ###################################### ### AMC SERVICES ### ###################################### # LICENSE LICENSE_CLIENT_URL = os.environ.get('LICENSE_CLIENT_URL', 'http://license-client:8050') LICENSE_CACHE_TIMEOUT = 60 * 60 # 60 minutes LICENSE_FEATURE_EVENT_PROCESSING = "event_processing" LICENSE_OPTION_EVENT_SOURCE_COUNT = "event_sources" # NGINX NGINX_ENABLED_CONFIG_FILENAME = "armaconsole.nginx" NGINX_HTTP_CONFIG_FILENAME = "armaconsole_http.nginx" NGINX_HTTPS_CONFIG_FILENAME = "armaconsole_https.nginx" NGINX_SITES_AVAILABLE = "/usr/local/armaconsole/nginx" # CORRELATOR CORRELATOR_SEVERITY_LEVEL = int(os.environ.get('CORRELATOR_SEVERITY_LEVEL', 6)) CORRELATOR_AUTO_CATEGORY_NAME = os.environ.get('CORRELATOR_AUTO_CATEGORY_NAME', gettext_lazy('Auto')) CORRELATOR_URL = os.environ.get('CORRELATOR_URL', 'http://correlator:5566') # VECTOR LOGSTASH_CONFIG_DIR = os.environ.get('LOGSTASH_CONFIG_DIR', os.path.join(PUBLIC_DIR, 'vector')) # ELASTICSEARCH ELASTIC_URL = os.environ.get('ELASTIC_URL', 'http://elasticsearch:9200') elk_split = ELASTIC_URL.replace('http://', '').split(':') ELK_HOST = elk_split[0] if len(elk_split) >= 0 else 'elasticsearch' ELK_PORT = elk_split[1] if len(elk_split) > 0 else 9200 ELK_LOGIN = os.environ.get('ELASTIC_USER', 'elastic') ELK_PASS = os.environ.get('ELASTIC_PASSWORD', 'changeme') ELK_MAX_ENTRIES = 100000 ELK_AGGREGATED_INDEX = 'aggregated-*' ELK_FIREWALL_PRODUCT_NAME = 'Industrial Firerwall' # Yes this is mistake, but it is how now Vector parses IF logs ELK_ENDPOINT_PRODUCT_NAME = 'Industrial Endpoint' # RABBITMQ RABBIT_URL = os.environ.get('RABBIT_URL', 'http://rabbitmq-management:5672') rabbit_split = RABBIT_URL.replace('http://', '').split(':') RABBIT_HOST = rabbit_split[0] if len(rabbit_split) >= 0 else 'rabbitmq-management' RABBIT_PORT = rabbit_split[1] if len(rabbit_split) > 0 else 5672 ############################### ### OTHER ### ############################### # ROUTING ROOT_URLCONF = 'console.urls' WSGI_APPLICATION = 'console.wsgi.application' ASGI_APPLICATION = 'console.asgi.application' LOGIN_REDIRECT_URL = 'index' LOGOUT_REDIRECT_URL = 'login' LOGIN_URL = 'login' CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [(REDIS_HOST, REDIS_PORT)], }, }, } # TEMPLATES TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], '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', ], }, }, ] # Site info must not contain dynamic data, only static values SITE_INFO = { 'domain': 'infowatch.ru', 'name': 'InfoWatch ARMA', 'package': 'armaconsole', # Must be a valid deb package name 'version': '1.4.0', # Must be a valid deb package version 'architecture': 'amd64', # Must be a valid deb package architecture # These values are used in CEF format 'vendor': 'InfoWatch ARMA', 'product': 'ARMAMC' } # How many (in percent) keep in table while rotation occurs # So 0.3 - means 30% of table will stay while rotation SAVE_DURING_ROTATION = float(os.environ.get('SAVE_DURING_ROTATION', 0.3)) EMAIL_HOST_USER = 'console@arma.com' EMAIL_HOST = 'localhost' # GENERATE SELFSIGNED CERTIFICATE TLS_CERT_DAYS = 365 TLS_CERT_KEY_SIZE = 2048 TLS_CERT_COUNTRY = "RU" TLS_CERT_STATE = "Moscow" TLS_CERT_LOCALITY = "Moscow" TLS_CERT_ORIG_NAME = "ARMA" TLS_CERT_UNIT_NAME = "Console" TLS_CERT_COMMON_NAME = "iwarma.ru" TLS_CERT_FILENAME = "/etc/nginx/ssl/armaconsole/nginx-selfsigned.crt" TLS_CERT_KEY_FILENAME = "/etc/nginx/ssl/armaconsole/nginx-selfsigned.key" # TODO: need use TLS_CERT_DHPARAM_FILENAME = "/etc/nginx/ssl/armaconsole/dhparam.pem" WEB_UI_PORT = int(os.environ.get('WEB_UI_PORT', 9090)) MAX_UPLOADSIZE = 80 * 1024 * 1024 # NCIRCC NCIRCC_DOMAIN_NAME = os.environ.get('NCIRCC_DOMAIN_NAME', 'https://test-lk.cert.gov.ru') NCIRCC_CERT_VERIFY = '/etc/ssl/certs/' if os.path.exists('/etc/ssl/certs/') else False # Compatible ARMAIF versions MINIMAL_COMPATIBLE_AIF_VERSION = "3.6" MINIMAL_VERSION_CORRELATION_RULES = '1.3.4' # Product version PRODUCT_VERSION = load_product_version()