Beispiel #1
0
class Base(Core):
    """Settings that may change per-environment, some with defaults."""

    # Flags that affect other settings, via setting methods below
    LOGGING_USE_JSON = values.BooleanValue(False)
    USE_OIDC = values.BooleanValue(False)

    # General settings
    DEBUG = values.BooleanValue(False)
    ADMINS = values.SingleNestedListValue([])
    SILENCED_SYSTEM_CHECKS = values.ListValue([
        # Check CSRF cookie http only. disabled because we read the
        # CSRF cookie in JS for forms in React.
        'security.W017',
    ])

    # Authentication
    def AUTHENTICATION_BACKENDS(self):
        if self.USE_OIDC:
            return ['normandy.base.auth_backends.LoggingRemoteUserBackend']
        else:
            return ['normandy.base.auth_backends.LoggingModelBackend']

    OIDC_REMOTE_AUTH_HEADER = values.Value('HTTP_REMOTE_USER')
    OIDC_LOGOUT_URL = values.Value(None)

    # Middleware that _most_ environments will need. Subclasses can override this list.
    EXTRA_MIDDLEWARE = [
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
    ]

    def MIDDLEWARE(self):
        """
        Determine middleware by combining the core set and
        per-environment set.
        """
        middleware = Core.MIDDLEWARE + self.EXTRA_MIDDLEWARE
        if self.USE_OIDC:
            middleware.append('normandy.base.middleware.ConfigurableRemoteUserMiddleware')
        return middleware

    def LOGGING(self):
        return {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'json': {
                    '()': 'mozilla_cloud_services_logger.formatters.JsonLogFormatter',
                    'logger_name': 'normandy',
                },
                'development': {
                    'format': '%(levelname)s %(asctime)s %(name)s %(message)s',
                },
            },
            'handlers': {
                'console': {
                    'level': 'DEBUG',
                    'class': 'logging.StreamHandler',
                    'formatter': 'json' if self.LOGGING_USE_JSON else 'development',
                },
            },
            'root': {
                'handlers': ['console'],
                'level': 'WARNING',
            },
            'loggers': {
                'normandy': {
                    'propagate': False,
                    'handlers': ['console'],
                    'level': 'DEBUG',
                },
                'request.summary': {
                    'propagate': False,
                    'handlers': ['console'],
                    'level': 'DEBUG',
                },
            },
        }

    # Remote services
    DATABASES = values.DatabaseURLValue('postgres://postgres@localhost/normandy')
    CONN_MAX_AGE = values.IntegerValue(0)
    GEOIP2_DATABASE = values.Value(os.path.join(Core.BASE_DIR, 'GeoLite2-Country.mmdb'))
    # Email settings
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_USE_TLS = values.BooleanValue(True)
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_BACKEND = values.Value('django.core.mail.backends.smtp.EmailBackend')

    def RAVEN_CONFIG(self):
        version_path = os.path.join(Core.BASE_DIR, '__version__', 'tag')
        try:
            with open(version_path) as f:
                version = f.read().strip()
        except IOError:
            version = None

        return {
            'dsn': values.URLValue(None, environ_name='RAVEN_CONFIG_DSN'),
            'release': values.Value(version, environ_name='RAVEN_CONFIG_RELEASE'),
        }

    # statsd
    STATSD_HOST = values.Value('localhost')
    STATSD_PORT = values.IntegerValue(8125)
    STATSD_IPV6 = values.BooleanValue(False)
    STATSD_PREFIX = values.Value('normandy')
    STATSD_MAXUDPSIZE = values.IntegerValue(512)

    # Security settings
    SECRET_KEY = values.SecretValue()
    ALLOWED_HOSTS = values.ListValue([])
    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'},
    ]
    PASSWORD_HASHERS = values.ListValue([
        'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    ])
    USE_X_FORWARDED_HOST = values.BooleanValue(False)
    SECURE_PROXY_SSL_HEADER = values.TupleValue()
    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
    CSRF_COOKIE_HTTPONLY = values.BooleanValue(False)
    CSRF_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_SSL_REDIRECT = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([])
    SESSION_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
    X_FRAME_OPTIONS = values.Value('DENY')
    REQUIRE_RECIPE_AUTH = values.BooleanValue(True)

    # Media and static settings
    STATIC_URL = values.Value('/static/')
    STATIC_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'static'))
    MEDIA_URL = values.Value('/media/')
    MEDIA_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'media'))

    STATICFILES_DIRS = (
        os.path.join(Core.BASE_DIR, 'assets'),
    )

    # URL that the CDN exists at to front cached parts of the site, if any.
    CDN_URL = values.URLValue(None)
    # URL that bypasses any CDNs
    APP_SERVER_URL = values.URLValue(None)

    # URL for the CSP report-uri directive.
    CSP_REPORT_URI = values.Value('/__cspreport__')

    # Normandy settings
    ADMIN_ENABLED = values.BooleanValue(True)
    ACTION_IMPLEMENTATION_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 365)
    NUM_PROXIES = values.IntegerValue(0)
    API_CACHE_TIME = values.IntegerValue(30)
    API_CACHE_ENABLED = values.BooleanValue(True)

    # If true, approvals must come from two separate users. If false, the same
    # user can approve their own request.
    PEER_APPROVAL_ENFORCED = values.BooleanValue(True)

    # Autograph settings
    AUTOGRAPH_URL = values.Value()
    AUTOGRAPH_HAWK_ID = values.Value()
    AUTOGRAPH_HAWK_SECRET_KEY = values.Value()
    AUTOGRAPH_SIGNATURE_MAX_AGE = values.IntegerValue(60 * 60 * 24 * 7)
    AUTOGRAPH_X5U_CACHE_BUST = values.Value(None)

    # How many days before expiration to warn for expired certificates
    CERTIFICATES_EXPIRE_EARLY_DAYS = values.IntegerValue(None)

    PROD_DETAILS_DIR = values.Value(os.path.join(Core.BASE_DIR, 'product_details'))

    # AWS settings
    AWS_ACCESS_KEY_ID = values.Value()
    AWS_SECRET_ACCESS_KEY = values.Value()
    AWS_STORAGE_BUCKET_NAME = values.Value()

    GITHUB_URL = values.Value('https://github.com/mozilla/normandy')
Beispiel #2
0
class Base(Core, CORS, OIDC, Metrics):
    """Settings that may change per-environment, some with defaults."""

    # Flags that affect other settings, via setting methods below
    LOGGING_USE_JSON = values.BooleanValue(False)
    USE_OIDC = values.BooleanValue(False)

    # General settings
    DEBUG = values.BooleanValue(False)
    ADMINS = values.SingleNestedListValue([])
    SILENCED_SYSTEM_CHECKS = values.ListValue([
        # We've subclassed Django's security middleware, so Django's
        # checks can't tell we are using the middleware.
        "security.W001",
        # We have disabled CSRF as we do not use cookie-based authentication.
        # As a result the CSRF middleware check is not required.
        "security.W003",
    ])

    # Authentication
    def AUTHENTICATION_BACKENDS(self):
        if self.USE_OIDC:
            return ["normandy.base.auth_backends.EmailOnlyRemoteUserBackend"]
        else:
            return ["normandy.base.auth_backends.LoggingModelBackend"]

    OIDC_REMOTE_AUTH_HEADER = values.Value("HTTP_REMOTE_USER")

    # Middleware that _most_ environments will need. Subclasses can override this list.
    EXTRA_MIDDLEWARE = [
        "django.contrib.sessions.middleware.SessionMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "django.contrib.messages.middleware.MessageMiddleware",
    ]

    def MIDDLEWARE(self):
        """
        Determine middleware by combining the core set and
        per-environment set.
        """
        middleware = Core.MIDDLEWARE + self.EXTRA_MIDDLEWARE
        if self.USE_OIDC:
            middleware.append(
                "normandy.base.middleware.ConfigurableRemoteUserMiddleware")
        return middleware

    def LOGGING(self):
        return {
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "json": {
                    "()": "dockerflow.logging.JsonLogFormatter",
                    "logger_name": "normandy"
                },
                "development": {
                    "format": "%(levelname)s %(asctime)s %(name)s %(message)s"
                },
            },
            "handlers": {
                "console": {
                    "level":
                    "DEBUG",
                    "class":
                    "logging.StreamHandler",
                    "formatter":
                    "json" if self.LOGGING_USE_JSON else "development",
                }
            },
            "root": {
                "handlers": ["console"],
                "level": "WARNING"
            },
            "loggers": {
                "normandy": {
                    "propagate": False,
                    "handlers": ["console"],
                    "level": "DEBUG"
                },
                "request.summary": {
                    "propagate": False,
                    "handlers": ["console"],
                    "level": "DEBUG"
                },
            },
        }

    # Remote services
    DATABASES = values.DatabaseURLValue(
        "postgres://postgres@localhost/normandy")
    CONN_MAX_AGE = values.IntegerValue(0)
    GEOIP2_DATABASE = values.Value(
        os.path.join(Core.BASE_DIR, "GeoLite2-Country.mmdb"))
    # Email settings
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_USE_TLS = values.BooleanValue(True)
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_BACKEND = values.Value("django.core.mail.backends.smtp.EmailBackend")

    def RAVEN_CONFIG(self):
        version_path = os.path.join(Core.BASE_DIR, "version.json")
        try:
            with open(version_path) as f:
                build_info = json.loads(f.read())
                version = build_info.get("version")
        except IOError:
            version = None

        return {
            "dsn": values.URLValue(None, environ_name="RAVEN_CONFIG_DSN"),
            "release": values.Value(version,
                                    environ_name="RAVEN_CONFIG_RELEASE"),
        }

    # statsd
    STATSD_HOST = values.Value("localhost")
    STATSD_PORT = values.IntegerValue(8125)
    STATSD_IPV6 = values.BooleanValue(False)
    STATSD_PREFIX = values.Value("normandy")
    STATSD_MAXUDPSIZE = values.IntegerValue(512)

    # Security settings
    SECRET_KEY = values.SecretValue()
    ALLOWED_HOSTS = values.ListValue([])
    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"
        },
    ]
    PASSWORD_HASHERS = values.ListValue([
        "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    ])
    USE_X_FORWARDED_HOST = values.BooleanValue(False)
    SECURE_PROXY_SSL_HEADER = values.TupleValue()
    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
    CSRF_COOKIE_HTTPONLY = values.BooleanValue(True)
    CSRF_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_SSL_REDIRECT = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([])
    SESSION_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
    X_FRAME_OPTIONS = values.Value("DENY")
    REQUIRE_RECIPE_AUTH = values.BooleanValue(True)

    # Media and static settings
    STATIC_URL = values.Value("/static/")
    STATIC_ROOT = values.Value(os.path.join(Core.BASE_DIR, "static"))
    MEDIA_URL = values.Value("/media/")
    MEDIA_ROOT = values.Value(os.path.join(Core.BASE_DIR, "media"))

    STATICFILES_DIRS = (os.path.join(Core.BASE_DIR, "assets"), )

    # URL that the CDN exists at to front cached parts of the site, if any.
    CDN_URL = values.URLValue(None)
    # URL that bypasses any CDNs
    APP_SERVER_URL = values.URLValue(None)

    # URL for the CSP report-uri directive.
    CSP_REPORT_URI = values.Value("/__cspreport__")

    # Normandy settings
    ADMIN_ENABLED = values.BooleanValue(True)
    IMMUTABLE_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 365)
    NUM_PROXIES = values.IntegerValue(0)
    API_CACHE_TIME = values.IntegerValue(30)
    API_CACHE_ENABLED = values.BooleanValue(True)
    PERMANENT_REDIRECT_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 30)
    HTTPS_REDIRECT_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 30)

    # If true, approvals must come from two separate users. If false, the same
    # user can approve their own request.
    PEER_APPROVAL_ENFORCED = values.BooleanValue(True)

    # Autograph settings
    AUTOGRAPH_URL = values.Value()
    AUTOGRAPH_HAWK_ID = values.Value()
    AUTOGRAPH_HAWK_SECRET_KEY = values.Value()
    AUTOGRAPH_SIGNATURE_MAX_AGE = values.IntegerValue(60 * 60 * 24 * 7)
    AUTOGRAPH_X5U_CACHE_BUST = values.Value(None)

    # Remote Settings connection configuration
    REMOTE_SETTINGS_URL = values.Value()
    REMOTE_SETTINGS_USERNAME = values.Value()
    REMOTE_SETTINGS_PASSWORD = values.Value()
    REMOTE_SETTINGS_BUCKET_ID = values.Value("main-workspace")
    REMOTE_SETTINGS_COLLECTION_ID = values.Value("normandy-recipes")
    REMOTE_SETTINGS_RETRY_REQUESTS = values.IntegerValue(3)

    # How many days before expiration to warn for expired certificates
    CERTIFICATES_EXPIRE_EARLY_DAYS = values.IntegerValue(None)
    CERTIFICATES_CHECK_VALIDITY = values.BooleanValue(True)
    CERTIFICATES_EXPECTED_ROOT_HASH = values.Value(None)
    CERTIFICATES_EXPECTED_SUBJECT_CN = values.Value(
        "normandy.content-signature.mozilla.org")

    # Storage settings
    DEFAULT_FILE_STORAGE = values.Value(
        "normandy.base.storage.NormandyS3Boto3Storage")

    PROD_DETAILS_DIR = values.Value(
        os.path.join(Core.BASE_DIR, "product_details"))

    # AWS settings
    AWS_ACCESS_KEY_ID = values.Value()
    AWS_SECRET_ACCESS_KEY = values.Value()
    AWS_STORAGE_BUCKET_NAME = values.Value()
    GS_BUCKET_NAME = values.Value()
    GS_DEFAULT_ACL = values.Value("publicRead")

    GITHUB_URL = values.Value("https://github.com/mozilla/normandy")
class Settings(Configuration):
    ACCESS_TOKEN_LIFETIME_MINUTES = values.FloatValue()
    ADMIN_HEADER_COLOR = values.Value()
    ADMIN_HEADER_TITLE = "{environment}{title}".format(
        environment=ENVIRONMENT or '{DJANGO_ENVIRONMENT}',
        title=values.Value('{DJANGO_ADMIN_HEADER_TITLE}',
                           environ_name='ADMIN_HEADER_TITLE'),
    )
    ADMINS = values.SingleNestedListValue([])
    ALLOWED_HOSTS = values.ListValue([])
    ANYMAIL = values.DictValue()
    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',
        },
    ]
    AUTH_USER_MODEL = "main.User"
    CORS_ORIGIN_WHITELIST = values.ListValue([])
    DATABASE_ENGINE = values.Value(environ_required=True)
    DATABASE_NAME = values.Value(environ_required=True)
    DATABASE_USER = values.Value()
    DATABASE_PASSWORD = values.Value()
    DATABASE_HOST = values.Value()
    DATABASE_PORT = values.Value()

    @property
    def DATABASES(self):
        return {
            'default': {
                'ENGINE': self.DATABASE_ENGINE,
                'NAME': self.DATABASE_NAME,
                'USER': self.DATABASE_USER,
                'PASSWORD': self.DATABASE_PASSWORD,
                'HOST': self.DATABASE_HOST,
                'PORT': self.DATABASE_PORT,
            }
        }

    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = values.BooleanValue(False)
    DEFAULT_FROM_EMAIL = values.Value()
    ELASTICSEARCH_HOST = values.Value()
    ELASTICSEARCH_PORT = values.Value()

    @property
    def ELASTICSEARCH_DSL(self):
        # https://django-configurations.readthedocs.io/en/stable/patterns/#property-settings
        return {
            'default': {
                'hosts':
                'http://{}:{}'.format(self.ELASTICSEARCH_HOST,
                                      self.ELASTICSEARCH_PORT)
            }
        }

    EMAIL_BACKEND = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_HOST_USER = values.Value()
    EMAIL_PORT = values.Value()
    EMAIL_USE_TLS = values.BooleanValue(False)
    INSTALLED_APPS = [
        # Django apps
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        # Third party
        'anymail',
        'django_extensions',
        'django_elasticsearch_dsl',
        'rest_framework',
        'rest_framework_simplejwt.token_blacklist',
        'corsheaders',
        'django_filters',
        # Local apps
        'main.apps.MainConfig'
    ]
    LANGUAGE_CODE = values.Value('en-us')
    LOGGING = logging_config()
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'whitenoise.middleware.WhiteNoiseMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'main.middleware.timezone_middleware.TimezoneMiddleware',
    ]
    RECAPTCHA_PRIVATE_KEY = values.SecretValue()
    RECAPTCHA_URL = values.Value(
        default="https://www.google.com/recaptcha/api/siteverify")
    REST_FRAMEWORK = {
        'DATETIME_FORMAT':
        '%Y-%m-%d %H:%M:%S',
        'DEFAULT_AUTHENTICATION_CLASSES':
        ('rest_framework_simplejwt.authentication.JWTAuthentication', ),
        'DEFAULT_PERMISSION_CLASSES':
        ('rest_framework.permissions.IsAuthenticated', ),
        'DEFAULT_RENDERER_CLASSES':
        ('rest_framework.renderers.JSONRenderer', ),
        'DEFAULT_VERSIONING_CLASS':
        'rest_framework.versioning.NamespaceVersioning',
    }
    ROOT_URLCONF = 'storageofknowledge.urls'
    SECRET_KEY = values.SecretValue()
    SERVER_EMAIL = values.Value()
    SESSION_COOKIE_AGE = values.IntegerValue(5 * 60)  # 5 minutes
    SESSION_SAVE_EVERY_REQUEST = values.BooleanValue(True)

    @property
    def SIMPLE_JWT(self):
        # https://django-configurations.readthedocs.io/en/stable/patterns/#property-settings
        return {
            'ROTATE_REFRESH_TOKENS':
            True,
            'ACCESS_TOKEN_LIFETIME':
            timedelta(minutes=self.ACCESS_TOKEN_LIFETIME_MINUTES)
        }

    STATIC_ROOT = values.Value(None)
    STATIC_URL = '/static/'
    STATICFILES_DIRS = values.SingleNestedListValue([])
    STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [(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',
                    'django.template.context_processors.media',
                    'main.context_processors.from_settings',
                ],
            },
        },
    ]
    TIME_ZONE = 'UTC'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = True
    USER_CONFIRMATION_LIFETIME_HOURS = values.FloatValue()
    WSGI_APPLICATION = 'storageofknowledge.wsgi.application'
class Base(Configuration, Celery):
    # Web Settings

    SECRET_KEY = values.SecretValue()

    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'ugrryo)w9y0(*i^-zjq+%)=o^g*-0l%l*7!5qzrg3j$y3mtp*$'

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

    @property
    def CACHES(self):
        return {
            'default': {
                'BACKEND': 'django_redis.cache.RedisCache',
                'LOCATION': self.REDIS_URL,
                'OPTIONS': {
                    'COMPRESSOR':
                    'django_redis.compressors.zlib.ZlibCompressor',  # noqa
                    'SERIALIZER':
                    'django_redis.serializers.json.JSONSerializer',  # noqa
                },
            },
        }

    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',
        },
    ]

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

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

    LANGUAGE_CODE = 'en-us'

    TIME_ZONE = values.Value('UTC', environ_prefix=None)

    USE_I18N = True

    USE_L10N = True

    USE_TZ = True

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

    CONN_MAX_AGE = values.IntegerValue(60, environ_prefix=None)

    ALLOWED_HOSTS = values.ListValue([], environ_prefix=None)

    CORS_ORIGIN = values.Value(environ_prefix=None)

    USE_X_FORWARDED_HOST = values.BooleanValue(False, environ_prefix=None)

    # Application definition
    INSTALLED_APPS = [
        'relops_hardware_controller.apps.RelopsHardwareControllerAppConfig',
        'relops_hardware_controller.api',
        'django_celery_results',
        'rest_framework',
    ]

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    ROOT_URLCONF = 'relops_hardware_controller.urls'

    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',
                ],
            },
        },
    ]

    WSGI_APPLICATION = 'relops_hardware_controller.wsgi.application'

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
    SESSION_CACHE_ALIAS = 'default'

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (),
        'DEFAULT_RENDERER_CLASSES':
        ('rest_framework.renderers.JSONRenderer', ),
        'UNAUTHENTICATED_USER':
        '******',
    }

    TASKCLUSTER_CLIENT_ID = values.Value(environ_prefix=None)
    TASKCLUSTER_ACCESS_TOKEN = values.SecretValue(environ_prefix=None)

    TASK_NAMES = values.ListValue([
        'ping',
        'status',
        'reboot',
        'ipmi_off',
        'ipmi_on',
        'ipmi_list',
        'ipmi_cycle',
        'ipmi_reset',
        'reimage',
        'loan',
        'return_loan',
    ],
                                  environ_prefix=None)

    REQUIRED_TASKCLUSTER_SCOPE_SETS = values.SingleNestedListValue(
        [['project:releng:roller:{}'.format(task_name)]
         for task_name in TASK_NAMES.value],
        seq_separator=',',
        environ_prefix=None)

    VALID_WORKER_ID_REGEX = values.Value('^.*', environ_prefix=None)

    # Worker Settings

    NOTIFY_EMAIL = values.Value('*****@*****.**', environ_prefix=None)
    NOTIFY_IRC_CHANNEL = values.Value('#roller', environ_prefix=None)

    BUGZILLA_URL = values.URLValue('https://bugzilla.mozilla.org',
                                   environ_prefix=None)
    BUGZILLA_API_KEY = values.SecretValue(environ_prefix=None)
    BUGZILLA_REOPEN_STATE = values.Value('REOPENED', environ_prefix=None)
    BUGZILLA_REBOOT_TEMPLATE = values.Value(json.dumps(
        dict(
            api_key='${api_key}',
            product='Infrastructure & Operations',
            component='DCOps',
            cc='${cc}',
            summary='${hostname} is unreachable',
            version='unspecified',
            description=
            'Reboot ${hostname} ${ip}\nRequested by ${client_id}\nRelops controller action failed:${log}',
            blocks='${blocks}',
        )),
                                            environ_prefix=None)

    BUGZILLA_WORKER_TRACKER_TEMPLATE = values.Value(json.dumps(
        dict(
            api_key='${api_key}',
            product='Infrastructure & Operations',
            component='CIDuty',
            summary='[${DC}] ${alias} problem tracking',
            version='unspecified',
            alias='${alias}',
        )),
                                                    environ_prefix=None)

    XEN_URL = values.URLValue('', environ_prefix=None)
    XEN_USERNAME = values.Value('', environ_prefix=None)
    XEN_PASSWORD = values.Value('', environ_prefix=None)

    ILO_USERNAME = values.Value('', environ_prefix=None)
    ILO_PASSWORD = values.Value('', environ_prefix=None)

    WORKER_CONFIG = JSONFileValue('',
                                  environ_prefix=None,
                                  environ_name='WORKER_CONFIG_PATH')

    # how many seconds to wait for a machine to go down and come back up
    DOWN_TIMEOUT = values.IntegerValue(60, environ_prefix=None)
    UP_TIMEOUT = values.IntegerValue(300, environ_prefix=None)

    REBOOT_METHODS = values.ListValue(
        [
            'ssh_reboot',
            'ipmi_reset',
            'ipmi_cycle',
            'snmp_reboot',  # snmp pdu for mac minis
            'file_bugzilla_bug',  # give up and file a bug
        ],
        environ_prefix=None)
Beispiel #5
0
class Base(Core):
    """Settings that may change per-environment, some with defaults."""
    # General settings
    DEBUG = values.BooleanValue(False)
    ADMINS = values.SingleNestedListValue([])

    # Remote services
    DATABASES = values.DatabaseURLValue(
        'postgres://postgres@localhost/normandy')
    GEOIP2_DATABASE = values.Value(
        os.path.join(Core.BASE_DIR, 'GeoLite2-Country.mmdb'))
    # Email settings
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_USE_TLS = values.BooleanValue(True)
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_BACKEND = values.Value('django.core.mail.backends.smtp.EmailBackend')
    RAVEN_CONFIG = {
        'dsn': values.URLValue(None, environ_name='RAVEN_CONFIG_DSN'),
    }
    PROD_DETAILS_STORAGE = values.Value(
        'normandy.recipes.storage.ProductDetailsRelationalStorage')
    # statsd
    STATSD_HOST = values.Value('localhost')
    STATSD_PORT = values.IntegerValue(8125)
    STATSD_IPV6 = values.BooleanValue(False)
    STATSD_PREFIX = values.Value('normandy')
    STATSD_MAXUDPSIZE = values.IntegerValue(512)

    # Security settings
    SECRET_KEY = values.SecretValue()
    ALLOWED_HOSTS = values.ListValue([])
    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'
        },
    ]
    PASSWORD_HASHERS = values.ListValue([
        'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    ])
    USE_X_FORWARDED_HOST = values.BooleanValue(False)
    SECURE_PROXY_SSL_HEADER = values.TupleValue()
    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
    CSRF_COOKIE_HTTPONLY = values.BooleanValue(True)
    CSRF_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_SSL_REDIRECT = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([])
    SESSION_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
    X_FRAME_OPTIONS = values.Value('DENY')

    # Media and static settings
    STATIC_URL = values.Value('/static/')
    STATIC_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'static'))
    MEDIA_URL = values.Value('/media/')
    MEDIA_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'media'))
    STATICFILES_STORAGE = values.Value(
        'normandy.storage.GzipManifestPipelineStorage')
    # Overwrite old files when uploading media.
    DEFAULT_FILE_STORAGE = values.Value(
        'storages.backends.overwrite.OverwriteStorage')
    # URL that the CDN exists at to front cached parts of the site, if any.
    CDN_URL = values.URLValue(None)

    # Normandy settings
    CAN_EDIT_ACTIONS_IN_USE = values.BooleanValue(False)
    ADMIN_ENABLED = values.BooleanValue(True)
    ACTION_IMPLEMENTATION_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 365)