0
0
Fork 0
mirror of https://github.com/alerta/alerta.git synced 2025-02-04 21:58:31 +00:00
alerta_alerta/alerta/utils/config.py
2020-05-06 10:54:33 +02:00

244 lines
9.3 KiB
Python

import ast
import logging
import os
from typing import List
from flask import Flask
from voluptuous import Email, MultipleInvalid, Schema, TypeInvalid, Url
LOG = logging.getLogger('alerta.config')
class Validate:
def __init__(self):
self.string_validator = Schema(str)
self.integer_validator = Schema(int)
self.list_string_validator = Schema([str])
self.list_integer_validator = Schema([int])
self.list_url_validator = Schema([Url()])
self.url_validator = Schema(Url())
self.email_validator = Schema(Email())
def validate_boolean(self, boolean_string: str) -> bool:
if boolean_string.lower() in ['true', '1', 'yes', 'y', 'on']:
variable_value = True
elif boolean_string.lower() in ['false', '0', 'no', 'n', 'off']:
variable_value = False
else:
raise ValueError('Could not parse boolean from environment variable')
return variable_value
def validate_url(self, url_string: str) -> (str, List[str]):
try:
if isinstance(url_string, list):
variable_value = []
for item in url_string:
self.url_validator(item)
variable_value = url_string
else:
variable_value = self.url_validator(url_string)
return variable_value
except (TypeInvalid, MultipleInvalid) as e:
raise RuntimeError('Unable to validate environment variable %s' % (e))
def validate_string(self, string_string: str) -> str:
try:
variable_value = self.string_validator(string_string)
return variable_value
except (TypeInvalid, MultipleInvalid) as e:
raise RuntimeError('Unable to validate environment variable %s' % (e))
def validate_email(self, email_string: str) -> str:
try:
variable_value = self.email_validator(email_string)
return variable_value
except (TypeInvalid, MultipleInvalid) as e:
raise RuntimeError('Unable to validate environment variable %s' % (e))
def validate_integer(self, integer_string: str) -> int:
try:
variable_value = self.integer_validator(int(integer_string))
return variable_value
except (TypeInvalid, MultipleInvalid) as e:
raise RuntimeError('Unable to validate environment variable %s' % (e))
def validate_list(self, list_string: str, list_type: str) -> List:
try:
list_data = ast.literal_eval(list_string)
if list_type == 'string':
variable_value = self.list_string_validator(list_data)
elif list_type == 'url':
variable_value = self.list_url_validator(list_data)
elif list_type == 'integer':
variable_value = self.list_integer_validator(list_data)
return variable_value
except (ValueError, TypeInvalid, MultipleInvalid, SyntaxError):
try:
# For backward compatibility
list_data = list_string.split(',')
if list_type == 'string':
variable_value = self.list_string_validator(list_data)
elif list_type == 'url':
variable_value = self.list_url_validator(list_data)
elif list_type == 'integer':
numbers = [int(x) for x in list_data]
variable_value = self.list_integer_validator(numbers)
return variable_value
except (TypeInvalid, MultipleInvalid) as e:
raise RuntimeError('Unable to validate environment variable %s' % (e))
class Config:
def __init__(self, app: Flask = None) -> None:
self.app = None
if app:
self.init_app(app)
def init_app(self, app: Flask) -> None:
config = self.get_user_config()
app.config.update(config)
@staticmethod
def get_user_config():
valid = Validate()
from flask import Config
config = Config('/')
config.from_object('alerta.settings')
config.from_pyfile('/etc/alertad.conf', silent=True)
config.from_envvar('ALERTA_SVR_CONF_FILE', silent=True)
if 'DEBUG' in os.environ:
config['DEBUG'] = valid.validate_boolean(os.environ['DEBUG'])
if 'BASE_URL' in os.environ:
config['BASE_URL'] = valid.validate_url(os.environ['BASE_URL'])
if 'USE_PROXYFIX' in os.environ:
config['USE_PROXYFIX'] = valid.validate_boolean(os.environ['USE_PROXYFIX'])
if 'SECRET_KEY' in os.environ:
config['SECRET_KEY'] = valid.validate_string(os.environ['SECRET_KEY'])
database_url = (
os.environ.get('DATABASE_URL', None)
# The following database settings are deprecated.
or os.environ.get('MONGO_URI', None)
or os.environ.get('MONGODB_URI', None)
or os.environ.get('MONGOHQ_URL', None)
or os.environ.get('MONGOLAB_URI', None)
)
# Use app config for DATABASE_URL if no env var from above override it
config['DATABASE_URL'] = database_url or config['DATABASE_URL']
if config['DATABASE_URL'] in os.environ:
config['DATABASE_URL'] = valid.validate_url(os.environ['DATABASE_URL'])
if 'DATABASE_NAME' in os.environ:
config['DATABASE_NAME'] = valid.validate_string(os.environ['DATABASE_NAME'])
if 'AUTH_REQUIRED' in os.environ:
config['AUTH_REQUIRED'] = valid.validate_boolean(os.environ['AUTH_REQUIRED'])
if 'AUTH_PROVIDER' in os.environ:
config['AUTH_PROVIDER'] = valid.validate_string(os.environ['AUTH_PROVIDER'])
if 'ADMIN_USERS' in os.environ:
config['ADMIN_USERS'] = valid.validate_list(os.environ['ADMIN_USERS'], 'string')
if 'SIGNUP_ENABLED' in os.environ:
config['SIGNUP_ENABLED'] = valid.validate_boolean(os.environ['SIGNUP_ENABLED'])
if 'CUSTOMER_VIEWS' in os.environ:
config['CUSTOMER_VIEWS'] = valid.validate_boolean(os.environ['CUSTOMER_VIEWS'])
if 'OAUTH2_CLIENT_ID' in os.environ:
config['OAUTH2_CLIENT_ID'] = valid.validate_string(os.environ['OAUTH2_CLIENT_ID'])
if 'OAUTH2_CLIENT_SECRET' in os.environ:
config['OAUTH2_CLIENT_SECRET'] = valid.validate_string(os.environ['OAUTH2_CLIENT_SECRET'])
if 'ALLOWED_EMAIL_DOMAINS' in os.environ:
config['ALLOWED_EMAIL_DOMAINS'] = valid.validate_list(os.environ['ALLOWED_EMAIL_DOMAINS'], 'string')
if 'AZURE_TENANT' in os.environ:
config['AZURE_TENANT'] = valid.validate_string(os.environ['AZURE_TENANT'])
if 'GITHUB_URL' in os.environ:
config['GITHUB_URL'] = valid.validate_url(os.environ['GITHUB_URL'])
if 'ALLOWED_GITHUB_ORGS' in os.environ:
config['ALLOWED_GITHUB_ORGS'] = valid.validate_list(os.environ['ALLOWED_GITHUB_ORGS'], 'string')
if 'GITLAB_URL' in os.environ:
config['GITLAB_URL'] = valid.validate_url(os.environ['GITLAB_URL'])
if 'ALLOWED_GITLAB_GROUPS' in os.environ:
config['ALLOWED_OIDC_ROLES'] = valid.validate_list(os.environ['ALLOWED_GITLAB_GROUPS'], 'string')
if 'KEYCLOAK_URL' in os.environ:
config['KEYCLOAK_URL'] = valid.validate_url(os.environ['KEYCLOAK_URL'])
if 'KEYCLOAK_REALM' in os.environ:
config['KEYCLOAK_REALM'] = valid.validate_string(os.environ['KEYCLOAK_REALM'])
if 'ALLOWED_KEYCLOAK_ROLES' in os.environ:
config['ALLOWED_OIDC_ROLES'] = valid.validate_list(os.environ['ALLOWED_KEYCLOAK_ROLES'], 'string')
if 'OIDC_ISSUER_URL' in os.environ:
config['OIDC_ISSUER_URL'] = valid.validate_url(os.environ['OIDC_ISSUER_URL'])
if 'ALLOWED_OIDC_ROLES' in os.environ:
config['ALLOWED_OIDC_ROLES'] = valid.validate_list(os.environ['ALLOWED_OIDC_ROLES'], 'string')
if 'CORS_ORIGINS' in os.environ:
config['CORS_ORIGINS'] = valid.validate_list(os.environ['CORS_ORIGINS'], 'url')
if 'MAIL_FROM' in os.environ:
config['MAIL_FROM'] = valid.validate_email(os.environ['MAIL_FROM'])
if 'SMTP_PASSWORD' in os.environ:
config['SMTP_PASSWORD'] = valid.validate_string(os.environ['SMTP_PASSWORD'])
if 'GOOGLE_TRACKING_ID' in os.environ:
config['GOOGLE_TRACKING_ID'] = valid.validate_string(os.environ['GOOGLE_TRACKING_ID'])
if 'PLUGINS' in os.environ:
config['PLUGINS'] = valid.validate_list(os.environ['PLUGINS'], 'string')
if 'ALERT_TIMEOUT' in os.environ:
config['ALERT_TIMEOUT'] = valid.validate_integer(os.environ['ALERT_TIMEOUT'])
if 'HEARTBEAT_TIMEOUT' in os.environ:
config['HEARTBEAT_TIMEOUT'] = valid.validate_integer(os.environ['HEARTBEAT_TIMEOUT'])
if 'API_KEY_EXPIRE_DAYS' in os.environ:
config['API_KEY_EXPIRE_DAYS'] = valid.validate_integer(os.environ['API_KEY_EXPIRE_DAYS'])
# Runtime config check
if config['CUSTOMER_VIEWS'] and not config['AUTH_REQUIRED']:
raise RuntimeError('Must enable authentication to use customer views')
if config['CUSTOMER_VIEWS'] and not config['ADMIN_USERS']:
raise RuntimeError('Customer views is enabled but there are no admin users')
return config