vvp -- VNF Validation Platform
[oom.git] / kubernetes / vvp / charts / vvp-em-uwsgi / resources / config / em / __init__.py
1 # Copyright © 2018 Amdocs, AT&T, Bell Canada
2 #
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
6 #
7 #       http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 """
16 Django settings for VVP project.
17
18 Environment variables that must exist:
19
20     ENVIRONMENT
21     SECRET_KEY
22     SECRET_WEBHOOK_TOKEN
23     SECRET_GITLAB_AUTH_TOKEN
24     SECRET_JENKINS_PASSWORD
25     SECRET_CMS_APP_CLIENT_ID
26     SECRET_CMS_APP_CLIENT_SECRET
27
28 Environment variables that must exist in production:
29
30     EMAIL_HOST
31     EMAIL_HOST_PASSWORD
32     EMAIL_HOST_USER
33     EMAIL_PORT
34
35 """
36
37 import os
38 from vvp.settings.envbool import envbool
39 from corsheaders.defaults import default_headers
40 from boto.s3.connection import OrdinaryCallingFormat
41 import datetime
42
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")
48
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']
54
55 # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
56 SECRET_KEY = os.environ["SECRET_KEY"]
57
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.
61 ALLOWED_HOSTS = ['*']
62
63 DEBUG = envbool('DJANGO_DEBUG_MODE', False)
64
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']
71 else:
72     EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
73
74 # Note: Only SSL email backends are allowed
75 EMAIL_USE_SSL = True
76
77 REST_FRAMEWORK = {
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',
81     'PAGE_SIZE': 10,
82     'DEFAULT_PERMISSION_CLASSES': (
83         'rest_framework.permissions.IsAuthenticated',
84     ),
85     'DEFAULT_AUTHENTICATION_CLASSES': (
86         'rest_framework.authentication.SessionAuthentication',
87         'rest_framework.authentication.BasicAuthentication',
88         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
89     ),
90     'DEFAULT_PARSER_CLASSES': (
91         'engagementmanager.rest.parsers.XSSJSONParser',
92         'engagementmanager.rest.parsers.XSSFormParser',
93         'engagementmanager.rest.parsers.XSSMultiPartParser',
94     )
95 }
96
97 JWT_AUTH = {
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',
102 }
103
104 APPEND_SLASH = False
105
106 # Application definition
107 INSTALLED_APPS = [
108     'django.contrib.auth',          # required by d.c.admin
109     'corsheaders',
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
115     'rest_framework',
116     'engagementmanager.apps.EngagementmanagerConfig',
117     'validationmanager.apps.ValidationmanagerConfig',
118 ]
119
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',
129 ]
130
131 ROOT_URLCONF = 'vvp.urls'
132
133 TEMPLATES = [
134     {
135         'BACKEND': 'django.template.backends.django.DjangoTemplates',
136         'DIRS': [PROJECT_PATH + '/web/templates'],
137         'APP_DIRS': True,
138         'OPTIONS': {
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
144             ],
145         },
146     },
147 ]
148
149 WSGI_APPLICATION = 'vvp.wsgi.application'
150
151
152 # Database
153 # https://docs.djangoproject.com/en/1.9/ref/settings/#databases
154 DATABASES = {
155     'default': {
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'],
162     }
163 }
164
165
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',
174         ]]
175
176
177 # Internationalization
178 # https://docs.djangoproject.com/en/1.9/topics/i18n/
179 LANGUAGE_CODE = 'en-us'
180 TIME_ZONE = 'UTC'
181 USE_I18N = True
182 USE_L10N = True
183 USE_TZ = True
184
185 CORS_ALLOW_HEADERS = default_headers + ('ICE-USER-ID',)
186
187 # Static files (CSS, JavaScript, Images)
188 # https://docs.djangoproject.com/en/1.9/howto/static-files/
189 STATIC_ROOT = os.environ['STATIC_ROOT']
190
191
192 LOGGING = {
193     'version': 1,
194     'disable_existing_loggers': False,
195     'formatters': {  # All possible attributes are: https://docs.python.org/3/library/logging.html#logrecord-attributes
196         'verbose': {
197             'format': '%(asctime)s %(levelname)s %(name)s %(module)s %(lineno)d %(process)d %(thread)d %(message)s'
198         },
199         'simple': {
200             'format': '%(asctime)s %(levelname)s %(name)s %(message)s'
201         },
202     },
203     'handlers': {
204         'console': {
205             'class': 'logging.StreamHandler',
206             'formatter': 'simple'
207         },
208         'vvp-info.log': {
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'
213         },
214         'vvp-debug.log': {
215             'level': 'DEBUG',
216             'class': 'logging.FileHandler',
217             'filename': os.path.join(LOGS_PATH, 'vvp-debug.log'),
218             'formatter': 'verbose'
219         },
220         'vvp-requests.log': {
221             'level': 'ERROR',
222             'class': 'logging.FileHandler',
223             'filename': os.path.join(LOGS_PATH, 'vvp-requests.log'),
224             'formatter': 'verbose'
225         },
226         'vvp-db.log': {
227             'level': 'ERROR',
228             'class': 'logging.FileHandler',
229             'filename': os.path.join(LOGS_PATH, 'vvp-db.log'),
230             'formatter': 'verbose',
231         },
232     },
233     'loggers': {
234         'vvp.logger': {
235             'handlers': ['vvp-info.log', 'vvp-debug.log', 'vvp-requests.log', 'vvp-db.log', 'console'],
236             'level': 'DEBUG' if DEBUG else 'INFO',
237         },
238         'django': {
239             'handlers': ['console'],
240             'level': 'INFO' if DEBUG else 'ERROR',
241         },
242         'django.request': {
243             'handlers': ['vvp-requests.log', 'console'],
244             'level': 'INFO' if DEBUG else 'ERROR',
245         },
246         'django.db.backends': {
247             'handlers': ['vvp-db.log', 'console'],
248             'level': 'DEBUG' if DEBUG else 'ERROR',
249             'propagate': False,
250         },
251         # silence the hundred lines of useless "missing variable in template"
252         # complaints per admin pageview.
253         'django.template': {
254             'level': 'DEBUG',
255             'handlers': ['vvp-info.log', 'vvp-debug.log', 'console'],
256             'propagate': False,
257         },
258     }
259 }
260
261
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
274 API_DOMAIN = 'em'
275
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
280 # no slash '/'.
281 # FIXME: Does this authentication scheme actually gain us anything? What's the
282 # threat model
283 WEBHOOK_TOKEN = os.environ['SECRET_WEBHOOK_TOKEN']
284
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/"
288
289 JENKINS_URL = "http://vvp-jenkins:8080/"
290 JENKINS_USERNAME = "admin"
291 JENKINS_PASSWORD = os.environ['SECRET_JENKINS_PASSWORD']
292
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']
299
300 # slack integration
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', '')
306
307 # S3 configuration for static resources storage and media upload
308
309 # used by our custom storage.py
310 MEDIA_BUCKET = "em-media"
311 STATIC_BUCKET = "em-static"
312
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
321
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'
327
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)
331
332 STATIC_ROOT = os.environ['STATIC_ROOT']