def get_format(self): """ Force static format for mongoDB and elasticsearch repositories """ if self.repository_type == 'data': repo = BaseAbstractRepository.search_repository( self.data_repository) if isinstance(repo, MongoDBRepository): return "@cee:{\\\"app_name\\\":\\\"%{app_name}e\\\",\\\"src_ip\\\":\\\"%a\\\",\\\"user\\\":\\\"%u\\\",\\\"time\\\":\\\"%{%Y-%m-%dT%H:%M:%S:%Z}t\\\",\\\"http_method\\\":\\\"%m\\\",\\\"requested_uri\\\":\\\"%U%q\\\",\\\"http_code\\\":%>s,\\\"incoming_protocol\\\":\\\"%H\\\",\\\"referer\\\":\\\"%{Referer}i\\\",\\\"user_agent\\\":\\\"%{User-agent}i\\\",\\\"size\\\":%B,\\\"bytes_received\\\":%I,\\\"bytes_sent\\\":%O,\\\"time_elapsed\\\":%D,\\\"country\\\":\\\"%{COUNTRY_CODE}e\\\",\\\"city\\\":\\\"%{CITY}e\\\",\\\"lat\\\":\\\"%{LATITUDE}e\\\",\\\"lon\\\":\\\"%{LONGITUDE}e\\\",\\\"reputation\\\":\\\"%{REPUTATION0}e,%{REPUTATION1}e,%{REPUTATION2}e,%{REPUTATION3}e,%{REPUTATION4}e\\\",\\\"owasp_top10\\\":\\\"%{owasp_top10}e\\\",\\\"reasons\\\":\\\"%{reasons}e\\\",\\\"threshold\\\":\\\"%{threshold}e\\\",\\\"score\\\":\\\"%{score}e\\\"}" elif isinstance(repo, ElasticSearchRepository): return "@cee:{\\\"app_name\\\":\\\"%{app_name}e\\\",\\\"src_ip\\\":\\\"%a\\\",\\\"user\\\":\\\"%u\\\",\\\"time\\\":\\\"%{%Y-%m-%dT%H:%M:%S%z}t\\\",\\\"http_method\\\":\\\"%m\\\",\\\"requested_uri\\\":\\\"%U%q\\\",\\\"http_code\\\":%>s,\\\"incoming_protocol\\\":\\\"%H\\\",\\\"referer\\\":\\\"%{Referer}i\\\",\\\"user_agent\\\":\\\"%{User-agent}i\\\",\\\"size\\\":%B,\\\"bytes_received\\\":%I,\\\"bytes_sent\\\":%O,\\\"time_elapsed\\\":%D,\\\"country\\\":\\\"%{COUNTRY_CODE}e\\\",\\\"city\\\":\\\"%{CITY}e\\\",\\\"lat\\\":\\\"%{LATITUDE}e\\\",\\\"lon\\\":\\\"%{LONGITUDE}e\\\",\\\"reputation\\\":\\\"%{REPUTATION0}e,%{REPUTATION1}e,%{REPUTATION2}e,%{REPUTATION3}e,%{REPUTATION4}e\\\",\\\"owasp_top10\\\":\\\"%{owasp_top10}e\\\",\\\"reasons\\\":\\\"%{reasons}e\\\",\\\"threshold\\\":\\\"%{threshold}e\\\",\\\"score\\\":\\\"%{score}e\\\"}" separators = { 'space': ' ', 'tab': '\t', 'comma': ',', 'semicolon': ';', 'underscore': '_', 'minus': '-' } sep = separators.get(self.separator, ' ') ret = "" for s in self.format.split(','): s = s.replace('%r', '\\"%r\\"') s = s.replace('%{Referer}i', '\\"%{Referer}i\\"') s = s.replace('%{User-agent}i', '\\"%{User-agent}i\\"') s = s.replace('%{app_name}e', '\\"%{app_name}e\\"') ret = ret + s + sep return ret[:-1]
def delete(self, request, repo_id, login=""): try: assert login, "Login missing." repo = BaseAbstractRepository.search_repository(repo_id) assert repo, "Authentication repository not found with id '{}'".format(repo_id) assert repo.repo_type == "auth", "Repository with id '{}' type is not authentication".format(repo_id) backend = repo.get_backend() except AssertionError as e: logger.error("RepositoriesAPI::POST: {}".format(e)) return JsonResponse({'status': False, 'error': str(e)}) try: # First check if that user is in repository if not self.check_user_exists(backend, login): return JsonResponse({'status': False, 'error': "User '{}' does not exists in repository " "'{}'".format(login, repo.repo_name)}) request_data = request.POST or request.JSON if not request_data.get('confirm'): return JsonResponse({'status': False, 'error': "Please send confirm=true to delete " "user {}.".format(login)}) backend.delete_user(login) return JsonResponse({ 'status': True }) except Exception as e: logger.critical(e, exc_info=1) return JsonResponse({ 'status': False, 'error': str(e) })
def setAutologonPassword(self, app_id, app_name, backend_id, username, old_password, new_password): result = None # SECURITY : Verify if the old password is correct ! if self.getAutologonPassword(app_id, backend_id, username) == old_password: # Update password pwd = SSOProfile() p = pwd.set_data( str(app_id), app_name, str(backend_id), BaseAbstractRepository.search_repository(backend_id).repo_name, username, 'vlt_autologon_password', new_password) if p: self.keys['password_' + str(backend_id)] = p result = self.handler.hset(self.key, 'password_' + str(backend_id), p) else: logger.info( "REDISPortalSession::setAutologonPassword: Unable to encrypt password " ) else: logger.info( "REDISPortalSession::setAutologonPassword: Wrong old_password : cannot set the new one" ) return result
def get(self, request, repo_id, login=""): """ Retrieve authentication repository with its id, and return informations from asked user """ try: assert login, "Login missing." repo = BaseAbstractRepository.search_repository(repo_id) assert repo, "Authentication repository not found with id '{}'".format(repo_id) assert repo.repo_type == "auth", "Repository with id '{}' type is not authentication".format(repo_id) except AssertionError as e: logger.error("RepositoriesAPI::GET: {}".format(e)) return JsonResponse({'status': False, 'error': str(e)}) try: user_infos = repo.get_backend().get_user_infos(login) return JsonResponse({ 'status': True, 'user_infos': user_infos }) except NotImplementedError: return JsonResponse({'status': False, 'error': "Get user informations on this type of repository is not supported yet."}) except Exception as e: logger.critical(e, exc_info=1) return JsonResponse({ 'status': False, 'error': str(e) })
def profile_list(request): """ Page dedicated to show application list """ # Retrieve unicity of (app_id, repo_id, login) profile_list = list( SSOProfile.objects.aggregate( { "$group": { "_id": { "login": "******", "app_id": "$app_id", "repo_id": "$repo_id" } } }, { "$project": { "_id": 0, "login": "******", "app_id": "$_id.app_id", "login": "******", "repo_id": "$_id.repo_id" } })) for profile in profile_list: profile['app_name'] = Application.objects.get( id=ObjectId(profile['app_id'])).name profile['repo_name'] = BaseAbstractRepository.search_repository( profile['repo_id']).repo_name return render_to_response('sso_profiles.html', {'profiles': profile_list}, context_instance=RequestContext(request))
def repository(self): """ Property used to map repository field to Repository Object :return: """ if self.repository_type == 'data': return BaseAbstractRepository.search_repository( self.data_repository) return self.repository_type
def repository(self): """ Property used to map repository field to Repository Object :return: """ if self.repository_type == 'data': from gui.models.repository_settings import BaseAbstractRepository return BaseAbstractRepository.search_repository(self.data_repository) return self.repository_type
def post(self, request, repo_id, login=""): try: assert login, "Login missing." repo = BaseAbstractRepository.search_repository(repo_id) assert repo, "Authentication repository not found with id '{}'".format(repo_id) assert repo.repo_type == "auth", "Repository with id '{}' type is not authentication".format(repo_id) backend = repo.get_backend() except AssertionError as e: logger.error("RepositoriesAPI::POST: {}".format(e)) return JsonResponse({'status': False, 'error': str(e)}) try: # First check if that user is in repository if self.check_user_exists(backend, login): return JsonResponse({'status': False, 'error': "User '{}' already exists in repository " "'{}'".format(login, repo.repo_name)}) # Check if fields are correctly filled-in request_data = request.POST or (request.JSON if hasattr(request, "JSON") else dict()) password = request_data.get('password') if not password: return JsonResponse({'status': False, 'error': "Password missing in POST data."}) login = login password = password email = request_data.get('email', "") phone = request_data.get('phone', "") kwargs = {} if isinstance(repo, LDAPRepository): group = request_data.get('group') update_group = request_data.get('update_group') if not group: return JsonResponse({'status': False, 'error': "Group is missing for adding user into LDAP repository."}) else: group = group kwargs['group'] = group kwargs['update_group'] = update_group backend.add_new_user(login, password, email, phone, **kwargs) return JsonResponse({ 'status': True }) except Exception as e: logger.critical(e, exc_info=1) return JsonResponse({ 'status': False, 'error': str(e) })
def put(self, request, repo_id, login=""): try: assert login, "Login missing." repo = BaseAbstractRepository.search_repository(repo_id) assert repo, "Authentication repository not found with id '{}'".format(repo_id) assert repo.repo_type == "auth", "Repository with id '{}' type is not authentication".format(repo_id) backend = repo.get_backend() except AssertionError as e: logger.error("RepositoriesAPI::POST: {}".format(e)) return JsonResponse({'status': False, 'error': str(e)}) try: # First check if that user is in repository if not self.check_user_exists(backend, login): return JsonResponse({'status': False, 'error': "User '{}' does not exists in repository " "'{}'".format(login, repo.repo_name)}) # Check if fields are correctly filled-in request_data = request.POST or request.JSON login = login email = request_data.get('email') phone = request_data.get('phone') password = request_data.get('password') if not email and not phone and not password: return JsonResponse({'status': False, 'error': "Password, Email and Phone missing in POST data. " "Nothing to do."}) if email: email = email if phone: phone = phone if email or phone: backend.update_user(login, email=email, phone=phone) if password: password = password backend.change_password(login, "", password) return JsonResponse({ 'status': True }) except Exception as e: logger.critical(e, exc_info=1) return JsonResponse({ 'status': False, 'error': str(e) })
def register_authentication(self, app_id, app_name, backend_id, url, dbauthentication_required, username, password, oauth2_token, app_token, authentication_datas, timeout): if dbauthentication_required: self.keys[backend_id] = 0 else: self.keys[backend_id] = 1 self.keys['url_' + app_id] = url self.keys['backend_' + app_id] = backend_id self.keys['login_' + backend_id] = username if oauth2_token: self.keys['oauth2_' + backend_id] = oauth2_token self.keys['app_id_' + backend_id] = app_id """ Make the link with precedent portal session to get the list of application cookies """ try: tmp = literal_eval(self.keys['app_list']) tmp.append(app_token) self.keys['app_list'] = str(tmp) except Exception as e: self.keys['app_list'] = str([app_token]) # WARNING : THE KEYS ARE NOT INITIALIZED ANYMORE ! # self.keys['otp'] = None # self.keys['authy_id'] = None # self.keys['user_phone'] = None # self.keys['user_mail'] = None """ Try to retrieve user phone from authentication_results """ self.keys['user_phone'] = authentication_datas.get('user_phone', 'N/A') self.keys['user_email'] = authentication_datas.get('user_email', 'N/A') if password: # Encrypt the password with the application id and user login and store it in portal session pwd = SSOProfile() p = pwd.set_data( app_id, app_name, backend_id, BaseAbstractRepository.search_repository(backend_id).repo_name, username, 'vlt_autologon_password', password) self.keys['password_' + backend_id] = p if not self.write_in_redis(timeout or self.default_timeout): raise REDISWriteError( "REDISPortalSession::register_authentication: Unable to write authentication infos in REDIS" ) return self.key
def authenticate(self, user_id, key, **kwargs): totp = TOTP(user_id) if not totp.verify(key): raise AuthenticationError("TOTP taped token is not valid.") logger.info( "TOTP Token for user {} successfully verified.".format(user_id)) # If the SSOProfile is not yet in MongoDB, set-it app_id = kwargs['app'] app_name = kwargs['app_name'] backend_id = kwargs['backend'] login = kwargs['login'] try: aes = AESCipher("{}{}{}{}{}".format(SECRET_KEY, app_id, backend_id, login, "totp")) encrypted_field = aes.key.hex() sso_profile = SSOProfile.objects.filter( encrypted_name=encrypted_field, login=login).first() if sso_profile: decrypted_value = sso_profile.get_data( sso_profile.encrypted_value, app_id, backend_id, login, "totp") if decrypted_value: logger.debug( "TOTP token for user '{}' retrieven from database.". format(login)) return True # SSOProfile not found -> Create it sso_profile = SSOProfile() sso_profile.set_data( app_id, app_name, backend_id, BaseAbstractRepository.search_repository( ObjectId(backend_id)).repo_name, login, "totp", user_id) logger.info( "TOTP token for user {} stored in database.".format(login)) # Save in Mongo sso_profile.store() except Exception as e: logger.exception(e) raise e return True
def repository(self): """ Property used to map repository field to Repository Object :return: """ return BaseAbstractRepository.search_repository(self.logs_repository)
def __init__(self, *args, **kwargs): try: self.listeners = kwargs.pop('listeners') except KeyError: pass super(ApplicationForm, self).__init__(*args, **kwargs) self = bootstrap_tooltips(self) repo_lst = BaseAbstractRepository.get_auth_repositories() auth_repo_lst = list() for rep in repo_lst: auth_repo_lst.append(( ObjectId(rep.id), rep.repo_name, )) mod_sec_choices = list() for rule in ModSecRulesSet.objects(type_rule__nin=('wlbl', )): mod_sec_choices.append((ObjectId(rule.id), rule.name)) dataset_list = list() dataset_list.append(((None), "------------------------------")) for dataset in Dataset.objects(svm_built=True).only('name', 'id'): dataset_list.append((ObjectId(dataset.id), dataset.name)) client_certificate = [('', '---------')] for cert in SSLCertificate.objects(is_trusted_ca__ne=True).only( 'id', 'cn'): client_certificate.append(("%sSSLProxyCertificateFile-%s.txt" % (settings.CONF_DIR, cert.id), cert.cn)) COOCKIE_CIPHER = ( ('rc4', 'RC4 (128 bits)'), ('aes128', 'AES 128 (128 bits)'), ('aes256', 'AES 256 (256 bits)'), ) IP_REPUTATION = [] loganalyser_rules = Cluster.objects.get( ).system_settings.loganalyser_settings.loganalyser_rules for rule in loganalyser_rules: tags = rule.tags.split(',') for tag in tags: IP_REPUTATION.append((tag, tag.capitalize())) GEOIP = [] for tag in [ "AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BQ", "BA", "BW", "BV", "BR", "IO", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CG", "CD", "CK", "CR", "CI", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "SV", "GQ", "ER", "EE", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "VA", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "KP", "KR", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "SS", "ES", "LK", "SD", "SR", "SJ", "SZ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "UY", "UZ", "VU", "VE", "VN", "VG", "VI", "WF", "EH", "YE", "ZM", "ZW" ]: GEOIP.append((tag, tag)) self.fields['block_reputation'] = MultipleChoiceField( required=False, choices=set(IP_REPUTATION), widget=SelectMultiple(attrs={'class': 'form-control select2'})) self.fields['block_geoip'] = MultipleChoiceField( required=False, choices=set(GEOIP), widget=SelectMultiple(attrs={'class': 'form-control select2'})) self.fields['allow_geoip'] = MultipleChoiceField( required=False, choices=set(GEOIP), widget=SelectMultiple(attrs={'class': 'form-control select2'})) self.fields['template'].queryset = portalTemplate.objects.filter() self.fields['auth_backend'] = ChoiceField( choices=auth_repo_lst, required=False, widget=Select(attrs={'class': 'form-control'})) self.fields['auth_backend_fallbacks'] = MultipleChoiceField( choices=auth_repo_lst, required=False, widget=SelectMultiple(attrs={'class': 'form-control select2'})) self.fields['redirect_uri'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 80, 'rows': 1, 'class': 'form-control' })) self.fields['sso_capture_content'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 80, 'rows': 2, 'class': 'form-control' })) self.fields['sso_replace_pattern'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 40, 'rows': 2, 'class': 'form-control' })) self.fields['sso_replace_content'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 40, 'rows': 2, 'class': 'form-control' })) self.fields['sso_after_post_request'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 80, 'rows': 2, 'class': 'form-control' })) self.fields['rules_set'] = MultipleChoiceField( choices=mod_sec_choices, required=False, widget=SelectMultiple(attrs={'class': 'form-control'})) self.fields['datasets'] = ChoiceField( choices=dataset_list, required=False, widget=Select(attrs={'class': 'form-control'})) self.fields['ssl_protocol'] = ChoiceField( choices=SSL_PROTOCOLS, required=False, widget=Select(attrs={'class': 'form-control'})) self.fields['ssl_client_certificate'] = ChoiceField( choices=client_certificate, required=False, widget=Select(attrs={'class': 'form-control'})) self.fields['custom_vhost'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 80, 'rows': 15, 'class': 'form-control' })) self.fields['custom_location'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 80, 'rows': 15, 'class': 'form-control' })) self.fields['custom_proxy'] = CharField( required=False, widget=Textarea(attrs={ 'cols': 80, 'rows': 15, 'class': 'form-control' })) self.fields['cookie_cipher'] = ChoiceField( choices=COOCKIE_CIPHER, required=False, widget=Select(attrs={'class': 'form-control'})) if self.initial.get("auth_backend"): repo = BaseAbstractRepository.search_repository( self.initial.get('auth_backend')) if isinstance(repo, LDAPRepository): try: groups = [(x, x) for x in repo.get_backend().enumerate_groups()] except: groups = [] finally: self.fields['group_registration'] = ChoiceField( choices=groups, required=False, widget=Select(attrs={'class': 'form-control'}))
def stock_sso_field(self, username, field, value): try: sso_profile = self.retrieve_sso_profile(username, field) if not sso_profile: raise Exception("Cannot retrieve sso profile") except Exception as e: logger.debug("Cannot retrieve sso profile '{}' for user '{}' : {}".format(field, username, e)) try: sso_profile = SSOProfile() sso_profile.set_data(str(self.application.id), self.application.name, str(self.backend_id), BaseAbstractRepository.search_repository(self.backend_id).repo_name, str(username), str(field), str(value)) sso_profile.store() except Exception as e: logger.error("SSOForward::stock_sso_field: Unable to store SSO Profile (field={},username={}) : {}".format(field, username, str(e))) logger.exception(e)