From 008ca7b692cd5f76e37c68e23be9510065e1a110 Mon Sep 17 00:00:00 2001 From: George Helman Date: Wed, 23 Feb 2022 01:20:25 -0500 Subject: [PATCH] Create separate sentry envs for different envs --- config/settings/production.py | 1 + config/settings/review.py | 224 ++++++++++++++++++++++++++++++++++ config/settings/staging.py | 224 ++++++++++++++++++++++++++++++++++ 3 files changed, 449 insertions(+) create mode 100644 config/settings/review.py create mode 100644 config/settings/staging.py diff --git a/config/settings/production.py b/config/settings/production.py index 4d7f60e0..0b226de8 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -216,6 +216,7 @@ class MediaRootS3Boto3Storage(S3Boto3Storage): ) sentry_sdk.init( dsn=SENTRY_DSN, + environment=environment, integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()], ) diff --git a/config/settings/review.py b/config/settings/review.py new file mode 100644 index 00000000..41f8d669 --- /dev/null +++ b/config/settings/review.py @@ -0,0 +1,224 @@ +import logging + +import sentry_sdk + +from sentry_sdk.integrations.django import DjangoIntegration +from sentry_sdk.integrations.logging import LoggingIntegration +from sentry_sdk.integrations.celery import CeleryIntegration + + +from .base import * # noqa +from .base import env + +# GENERAL +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key +SECRET_KEY = env("DJANGO_SECRET_KEY") +# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts +ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[".herokuapp.com"]) +ENVIRONMENT = "REVIEW" + +# DATABASES +# ------------------------------------------------------------------------------ +DATABASES["default"] = env.db("DATABASE_URL") # noqa F405 +DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405 +DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405 + +# CACHES +# ------------------------------------------------------------------------------ +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": env("REDIS_URL"), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + # Mimicing memcache behavior. + # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior + "IGNORE_EXCEPTIONS": True, + }, + } +} + +# SECURITY +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect +SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) +# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure +SESSION_COOKIE_SECURE = True +# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure +CSRF_COOKIE_SECURE = True +# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds +# TODO: set this to 60 seconds first and then to 518400 once you prove the former works +SECURE_HSTS_SECONDS = 60 +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains +SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( + "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True +) +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload +SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True) +# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff +SECURE_CONTENT_TYPE_NOSNIFF = env.bool( + "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True +) + +# STORAGES +# ------------------------------------------------------------------------------ +# https://django-storages.readthedocs.io/en/latest/#installation +INSTALLED_APPS += ["storages"] # noqa F405 + +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID") +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY") +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_QUERYSTRING_AUTH = env.bool("DJANGO_AWS_QUERYSTRING_AUTH", default=True) +AWS_S3_ENCRYPTION = env.bool("DJANGO_AWS_S3_ENCRYPTION", default=True) +AWS_S3_SIGNATURE_VERSION = env("DJANGO_AWS_S3_SIGNATURE_VERSION", default="s3v4") +# DO NOT change these unless you know what you're doing. +_AWS_EXPIRY = 60 * 60 * 24 * 7 +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_S3_OBJECT_PARAMETERS = { + "CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate" +} +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_DEFAULT_ACL = None +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None) + + +# STATIC +# ------------------------ +STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" + +# MEDIA +# ------------------------------------------------------------------------------ +# region http://stackoverflow.com/questions/10390244/ +# Full-fledge class: https://stackoverflow.com/a/18046120/104731 +from storages.backends.s3boto3 import S3Boto3Storage # noqa E402 + + +class StaticRootS3Boto3Storage(S3Boto3Storage): + location = "static" + + +class MediaRootS3Boto3Storage(S3Boto3Storage): + location = "media" + file_overwrite = False + + +# endregion +DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage" +MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" + +# TEMPLATES +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#templates +TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405 + ( + "django.template.loaders.cached.Loader", + [ + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", + ], + ) +] + +# EMAIL +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email +DEFAULT_FROM_EMAIL = env( + "DJANGO_DEFAULT_FROM_EMAIL", default=f"DEAR Petition <{ALLOWED_HOSTS[0]}>" +) +# https://docs.djangoproject.com/en/dev/ref/settings/#server-email +SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL) +# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix +EMAIL_SUBJECT_PREFIX = env("DJANGO_EMAIL_SUBJECT_PREFIX", default="[DEAR Petition]") +EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" +EMAIL_HOST = "smtp.sendgrid.net" +EMAIL_HOST_USER = "apikey" +EMAIL_HOST_PASSWORD = env("SENDGRID_API_KEY") +EMAIL_PORT = 587 +EMAIL_USE_TLS = True + +# ADMIN +# ------------------------------------------------------------------------------ +# Django Admin URL regex. +ADMIN_URL = env("DJANGO_ADMIN_URL") + +# Gunicorn +# ------------------------------------------------------------------------------ +INSTALLED_APPS += ["gunicorn"] # noqa F405 + +# WhiteNoise +# ------------------------------------------------------------------------------ +# http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise +MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware") # noqa F405 + + +# LOGGING +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#logging +# See https://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +APP_LOG_LEVEL = env("APP_LOG_LEVEL", default="DEBUG") + +LOGGING = { + "version": 1, + "disable_existing_loggers": True, + "formatters": { + "verbose": { + "format": "%(levelname)s %(asctime)s %(name)s " + "%(process)d %(thread)d %(message)s" + } + }, + "handlers": { + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "verbose", + } + }, + "loggers": { + "django.db.backends": { + "level": "ERROR", + "handlers": ["console"], + "propagate": False, + }, + "dear_petition": { + "level": APP_LOG_LEVEL, + "handlers": ["console"], + "propagate": False, + }, + "ciprs": {"level": APP_LOG_LEVEL, "handlers": ["console"], "propagate": False}, + # Errors logged by the SDK itself + "sentry_sdk": {"level": "ERROR", "handlers": ["console"], "propagate": False}, + "django.security.DisallowedHost": { + "level": "ERROR", + "handlers": ["console"], + "propagate": False, + }, + }, +} + +# Sentry +# ------------------------------------------------------------------------------ +SENTRY_DSN = env("SENTRY_DSN") +SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO) + +sentry_logging = LoggingIntegration( + level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs + event_level=None, # Send no events from log messages +) +sentry_sdk.init( + dsn=SENTRY_DSN, + environment=environment, + integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()], +) + +# Your stuff... +# ------------------------------------------------------------------------------ diff --git a/config/settings/staging.py b/config/settings/staging.py new file mode 100644 index 00000000..e12f4b7e --- /dev/null +++ b/config/settings/staging.py @@ -0,0 +1,224 @@ +import logging + +import sentry_sdk + +from sentry_sdk.integrations.django import DjangoIntegration +from sentry_sdk.integrations.logging import LoggingIntegration +from sentry_sdk.integrations.celery import CeleryIntegration + + +from .base import * # noqa +from .base import env + +# GENERAL +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key +SECRET_KEY = env("DJANGO_SECRET_KEY") +# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts +ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[".herokuapp.com"]) +ENVIRONMENT = "STAGING" + +# DATABASES +# ------------------------------------------------------------------------------ +DATABASES["default"] = env.db("DATABASE_URL") # noqa F405 +DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405 +DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405 + +# CACHES +# ------------------------------------------------------------------------------ +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": env("REDIS_URL"), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + # Mimicing memcache behavior. + # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior + "IGNORE_EXCEPTIONS": True, + }, + } +} + +# SECURITY +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect +SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) +# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure +SESSION_COOKIE_SECURE = True +# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure +CSRF_COOKIE_SECURE = True +# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds +# TODO: set this to 60 seconds first and then to 518400 once you prove the former works +SECURE_HSTS_SECONDS = 60 +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains +SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( + "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True +) +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload +SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True) +# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff +SECURE_CONTENT_TYPE_NOSNIFF = env.bool( + "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True +) + +# STORAGES +# ------------------------------------------------------------------------------ +# https://django-storages.readthedocs.io/en/latest/#installation +INSTALLED_APPS += ["storages"] # noqa F405 + +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID") +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY") +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_QUERYSTRING_AUTH = env.bool("DJANGO_AWS_QUERYSTRING_AUTH", default=True) +AWS_S3_ENCRYPTION = env.bool("DJANGO_AWS_S3_ENCRYPTION", default=True) +AWS_S3_SIGNATURE_VERSION = env("DJANGO_AWS_S3_SIGNATURE_VERSION", default="s3v4") +# DO NOT change these unless you know what you're doing. +_AWS_EXPIRY = 60 * 60 * 24 * 7 +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_S3_OBJECT_PARAMETERS = { + "CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate" +} +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_DEFAULT_ACL = None +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None) + + +# STATIC +# ------------------------ +STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" + +# MEDIA +# ------------------------------------------------------------------------------ +# region http://stackoverflow.com/questions/10390244/ +# Full-fledge class: https://stackoverflow.com/a/18046120/104731 +from storages.backends.s3boto3 import S3Boto3Storage # noqa E402 + + +class StaticRootS3Boto3Storage(S3Boto3Storage): + location = "static" + + +class MediaRootS3Boto3Storage(S3Boto3Storage): + location = "media" + file_overwrite = False + + +# endregion +DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage" +MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" + +# TEMPLATES +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#templates +TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405 + ( + "django.template.loaders.cached.Loader", + [ + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", + ], + ) +] + +# EMAIL +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email +DEFAULT_FROM_EMAIL = env( + "DJANGO_DEFAULT_FROM_EMAIL", default=f"DEAR Petition <{ALLOWED_HOSTS[0]}>" +) +# https://docs.djangoproject.com/en/dev/ref/settings/#server-email +SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL) +# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix +EMAIL_SUBJECT_PREFIX = env("DJANGO_EMAIL_SUBJECT_PREFIX", default="[DEAR Petition]") +EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" +EMAIL_HOST = "smtp.sendgrid.net" +EMAIL_HOST_USER = "apikey" +EMAIL_HOST_PASSWORD = env("SENDGRID_API_KEY") +EMAIL_PORT = 587 +EMAIL_USE_TLS = True + +# ADMIN +# ------------------------------------------------------------------------------ +# Django Admin URL regex. +ADMIN_URL = env("DJANGO_ADMIN_URL") + +# Gunicorn +# ------------------------------------------------------------------------------ +INSTALLED_APPS += ["gunicorn"] # noqa F405 + +# WhiteNoise +# ------------------------------------------------------------------------------ +# http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise +MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware") # noqa F405 + + +# LOGGING +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#logging +# See https://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +APP_LOG_LEVEL = env("APP_LOG_LEVEL", default="DEBUG") + +LOGGING = { + "version": 1, + "disable_existing_loggers": True, + "formatters": { + "verbose": { + "format": "%(levelname)s %(asctime)s %(name)s " + "%(process)d %(thread)d %(message)s" + } + }, + "handlers": { + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "verbose", + } + }, + "loggers": { + "django.db.backends": { + "level": "ERROR", + "handlers": ["console"], + "propagate": False, + }, + "dear_petition": { + "level": APP_LOG_LEVEL, + "handlers": ["console"], + "propagate": False, + }, + "ciprs": {"level": APP_LOG_LEVEL, "handlers": ["console"], "propagate": False}, + # Errors logged by the SDK itself + "sentry_sdk": {"level": "ERROR", "handlers": ["console"], "propagate": False}, + "django.security.DisallowedHost": { + "level": "ERROR", + "handlers": ["console"], + "propagate": False, + }, + }, +} + +# Sentry +# ------------------------------------------------------------------------------ +SENTRY_DSN = env("SENTRY_DSN") +SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO) + +sentry_logging = LoggingIntegration( + level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs + event_level=None, # Send no events from log messages +) +sentry_sdk.init( + dsn=SENTRY_DSN, + environment=environment, + integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()], +) + +# Your stuff... +# ------------------------------------------------------------------------------