1 # Copyright © 2018 Amdocs, AT&T, Bell Canada
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 Django settings for VVP project.
18 Environment variables that must exist:
23 SECRET_GITLAB_AUTH_TOKEN
24 SECRET_JENKINS_PASSWORD
25 SECRET_CMS_APP_CLIENT_ID
26 SECRET_CMS_APP_CLIENT_SECRET
28 Environment variables that must exist in production:
38 from vvp.settings.envbool import envbool
39 from corsheaders.defaults import default_headers
40 from boto.s3.connection import OrdinaryCallingFormat
43 # With this file at ice/settings/__init__.py, we need three applications of
44 # dirname() to find the project root.
45 import engagementmanager
46 PROJECT_PATH = os.path.dirname(os.path.dirname(engagementmanager.__file__))
47 LOGS_PATH = os.path.join(PROJECT_PATH, "logs")
49 ENVIRONMENT = os.environ['ENVIRONMENT']
50 PROGRAM_NAME_URL_PREFIX = os.environ['PROGRAM_NAME_URL_PREFIX']
51 SERVICE_PROVIDER = os.environ['SERVICE_PROVIDER']
52 PROGRAM_NAME = os.environ['PROGRAM_NAME']
53 SERVICE_PROVIDER_DOMAIN = os.environ['SERVICE_PROVIDER_DOMAIN']
55 # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
56 SECRET_KEY = os.environ["SECRET_KEY"]
58 # https://docs.djangoproject.com/en/1.10/ref/settings/#allowed-hosts
59 # Anything in the Host header that does not match our expected domain should
60 # raise SuspiciousOperation exception.
63 DEBUG = envbool('DJANGO_DEBUG_MODE', False)
65 if ENVIRONMENT == 'production':
66 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
67 EMAIL_HOST = os.environ['EMAIL_HOST']
68 EMAIL_HOST_PASSWORD = os.environ['EMAIL_HOST_PASSWORD']
69 EMAIL_HOST_USER = os.environ['EMAIL_HOST_USER']
70 EMAIL_PORT = os.environ['EMAIL_PORT']
72 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
74 # Note: Only SSL email backends are allowed
78 # Use Django's standard `django.contrib.auth` permissions,
79 # or allow read-only access for unauthenticated users.
80 'EXCEPTION_HANDLER': 'engagementmanager.utils.exception_handler.ice_exception_handler',
82 'DEFAULT_PERMISSION_CLASSES': (
83 'rest_framework.permissions.IsAuthenticated',
85 'DEFAULT_AUTHENTICATION_CLASSES': (
86 'rest_framework.authentication.SessionAuthentication',
87 'rest_framework.authentication.BasicAuthentication',
88 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
90 'DEFAULT_PARSER_CLASSES': (
91 'engagementmanager.rest.parsers.XSSJSONParser',
92 'engagementmanager.rest.parsers.XSSFormParser',
93 'engagementmanager.rest.parsers.XSSMultiPartParser',
98 'JWT_AUTH_HEADER_PREFIX': 'token',
99 'JWT_ALGORITHM': 'HS256',
100 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
101 'JWT_DECODE_HANDLER': 'engagementmanager.utils.authentication.ice_jwt_decode_handler',
106 # Application definition
108 'django.contrib.auth', # required by d.c.admin
110 'django.contrib.contenttypes', # required by d.c.admin
111 'django.contrib.sessions', # required by d.c.admin
112 'django.contrib.messages', # required by d.c.admin
113 'django.contrib.staticfiles',
114 'django.contrib.admin', # django admin site
116 'engagementmanager.apps.EngagementmanagerConfig',
117 'validationmanager.apps.ValidationmanagerConfig',
120 MIDDLEWARE_CLASSES = [
121 'django.middleware.security.SecurityMiddleware',
122 'django.contrib.sessions.middleware.SessionMiddleware',
123 'django.middleware.common.CommonMiddleware',
124 'django.contrib.auth.middleware.AuthenticationMiddleware', # required by d.c.admin
125 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
126 'django.contrib.messages.middleware.MessageMiddleware',
127 'django.middleware.clickjacking.XFrameOptionsMiddleware',
128 'corsheaders.middleware.CorsMiddleware',
131 ROOT_URLCONF = 'vvp.urls'
135 'BACKEND': 'django.template.backends.django.DjangoTemplates',
136 'DIRS': [PROJECT_PATH + '/web/templates'],
139 'context_processors': [
140 'django.template.context_processors.debug',
141 'django.template.context_processors.request',
142 'django.contrib.auth.context_processors.auth', # required by d.c.admin
143 'django.contrib.messages.context_processors.messages', # required by d.c.admin
149 WSGI_APPLICATION = 'vvp.wsgi.application'
153 # https://docs.djangoproject.com/en/1.9/ref/settings/#databases
156 'ENGINE': 'django.db.backends.postgresql',
157 'NAME': os.environ['PGDATABASE'],
158 'USER': os.environ['PGUSER'],
159 'PASSWORD': os.environ['PGPASSWORD'],
160 'HOST': os.environ['PGHOST'],
161 'PORT': os.environ['PGPORT'],
166 # Password validation
167 # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
168 AUTH_PASSWORD_VALIDATORS = [
169 {'NAME': 'django.contrib.auth.password_validation.%s' % s} for s in [
170 'UserAttributeSimilarityValidator',
171 'MinimumLengthValidator',
172 'CommonPasswordValidator',
173 'NumericPasswordValidator',
177 # Internationalization
178 # https://docs.djangoproject.com/en/1.9/topics/i18n/
179 LANGUAGE_CODE = 'en-us'
185 CORS_ALLOW_HEADERS = default_headers + ('ICE-USER-ID',)
187 # Static files (CSS, JavaScript, Images)
188 # https://docs.djangoproject.com/en/1.9/howto/static-files/
189 STATIC_ROOT = os.environ['STATIC_ROOT']
194 'disable_existing_loggers': False,
195 'formatters': { # All possible attributes are: https://docs.python.org/3/library/logging.html#logrecord-attributes
197 'format': '%(asctime)s %(levelname)s %(name)s %(module)s %(lineno)d %(process)d %(thread)d %(message)s'
200 'format': '%(asctime)s %(levelname)s %(name)s %(message)s'
205 'class': 'logging.StreamHandler',
206 'formatter': 'simple'
209 'level': 'INFO', # handler will ignore DEBUG (only process INFO, WARN, ERROR, CRITICAL, FATAL)
210 'class': 'logging.FileHandler',
211 'filename': os.path.join(LOGS_PATH, 'vvp-info.log'),
212 'formatter': 'verbose'
216 'class': 'logging.FileHandler',
217 'filename': os.path.join(LOGS_PATH, 'vvp-debug.log'),
218 'formatter': 'verbose'
220 'vvp-requests.log': {
222 'class': 'logging.FileHandler',
223 'filename': os.path.join(LOGS_PATH, 'vvp-requests.log'),
224 'formatter': 'verbose'
228 'class': 'logging.FileHandler',
229 'filename': os.path.join(LOGS_PATH, 'vvp-db.log'),
230 'formatter': 'verbose',
235 'handlers': ['vvp-info.log', 'vvp-debug.log', 'vvp-requests.log', 'vvp-db.log', 'console'],
236 'level': 'DEBUG' if DEBUG else 'INFO',
239 'handlers': ['console'],
240 'level': 'INFO' if DEBUG else 'ERROR',
243 'handlers': ['vvp-requests.log', 'console'],
244 'level': 'INFO' if DEBUG else 'ERROR',
246 'django.db.backends': {
247 'handlers': ['vvp-db.log', 'console'],
248 'level': 'DEBUG' if DEBUG else 'ERROR',
251 # silence the hundred lines of useless "missing variable in template"
252 # complaints per admin pageview.
255 'handlers': ['vvp-info.log', 'vvp-debug.log', 'console'],
262 #############################
263 # VVP Related Configuration
264 #############################
265 CONTACT_FROM_ADDRESS = os.getenv('CONTACT_FROM_ADDRESS', 'dummy@example.com')
266 CONTACT_EMAILS = [s.strip() for s in os.getenv('CONTACT_EMAILS', 'user@example.com').split(',') if s]
267 DOMAIN = os.getenv('EM_DOMAIN_NAME')
268 TOKEN_EXPIRATION_IN_HOURS = 48
269 DAILY_SCHEDULED_JOB_HOUR = 20
270 NUMBER_OF_POLLED_ACTIVITIES = 5
271 TEMP_PASSWORD_EXPIRATION_IN_HOURS = 48
272 # This is the DNS name pointing to the private-network ip of the host machine
273 # running (a haproxy that points to) (an nginx frontend for) this app
276 # The authentication token needed by Jenkins or Gitlab to issue webhook updates
277 # to us. This is a "secret" shared by Jenkins and Django. It must be part of
278 # the URL path component for the Jenkins webhook in ValidationManager to accept
279 # a notification. It should be a set of random URL-path-safe characters, with
281 # FIXME: Does this authentication scheme actually gain us anything? What's the
283 WEBHOOK_TOKEN = os.environ['SECRET_WEBHOOK_TOKEN']
285 # The authentication token and URL needed for us to issue requests to the GitLab API.
286 GITLAB_TOKEN = os.environ['SECRET_GITLAB_AUTH_TOKEN']
287 GITLAB_URL = "http://vvp-gitlab/"
289 JENKINS_URL = "http://vvp-jenkins:8080/"
290 JENKINS_USERNAME = "admin"
291 JENKINS_PASSWORD = os.environ['SECRET_JENKINS_PASSWORD']
293 IS_CL_CREATED_ON_REVIEW_STATE = envbool('IS_CL_CREATED_ON_REVIEW_STATE', False) # Options: True, False
294 IS_SIGNAL_ENABLED = envbool('IS_SIGNAL_ENABLED', True)
295 RECENT_ENG_TTL = 3 # In days
296 CMS_URL = "http://vvp-cms-uwsgi/api/"
297 CMS_APP_CLIENT_ID = os.environ['SECRET_CMS_APP_CLIENT_ID']
298 CMS_APP_CLIENT_SECRET = os.environ['SECRET_CMS_APP_CLIENT_SECRET']
301 SLACK_API_TOKEN = os.environ['SLACK_API_TOKEN']
302 ENGAGEMENTS_CHANNEL = os.getenv('ENGAGEMENTS_CHANNEL', '')
303 ENGAGEMENTS_NOTIFICATIONS_CHANNEL = os.getenv('ENGAGEMENTS_NOTIFICATIONS_CHANNEL:', '')
304 DEVOPS_CHANNEL = os.getenv('DEVOPS_CHANNEL', '')
305 DEVOPS_NOTIFICATIONS_CHANNEL = os.getenv('DEVOPS_NOTIFICATIONS_CHANNEL', '')
307 # S3 configuration for static resources storage and media upload
309 # used by our custom storage.py
310 MEDIA_BUCKET = "em-media"
311 STATIC_BUCKET = "em-static"
313 # django-storages configuration
314 AWS_S3_HOST = os.environ['S3_HOST']
315 AWS_S3_PORT = int(os.environ['S3_PORT'])
316 AWS_S3_CUSTOM_DOMAIN = os.environ['S3_HOST']
317 AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
318 AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
319 AWS_AUTO_CREATE_BUCKET = True
320 AWS_PRELOAD_METADATA = True
322 # Set by custom subclass.
323 # AWS_STORAGE_BUCKET_NAME = "em-static"
324 AWS_S3_CALLING_FORMAT = OrdinaryCallingFormat()
325 DEFAULT_FILE_STORAGE = 'vvp.settings.storage.S3MediaStorage'
326 STATICFILES_STORAGE = 'vvp.settings.storage.S3StaticStorage'
328 # These seem to have no effect even when we don't override with custom_domain?
329 STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, STATIC_BUCKET)
330 MEDIA_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, MEDIA_BUCKET)
332 STATIC_ROOT = os.environ['STATIC_ROOT']