From f186225aa8d80caa431044218a3a919b799881f0 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Sat, 26 Sep 2015 02:57:00 +0200 Subject: [PATCH] rename module; --- auth_brute_force/README.rst | 114 +++++++++++++ auth_brute_force/__init__.py | 3 + auth_brute_force/__openerp__.py | 42 +++++ auth_brute_force/controllers/__init__.py | 2 + auth_brute_force/controllers/controllers.py | 104 ++++++++++++ auth_brute_force/data/ir_config_parameter.xml | 29 ++++ auth_brute_force/i18n/auth_brute_force.pot | 150 ++++++++++++++++++ auth_brute_force/i18n/fr.po | 120 ++++++++++++++ auth_brute_force/models/__init__.py | 3 + .../models/res_authentication_attempt.py | 58 +++++++ auth_brute_force/models/res_banned_remote.py | 71 +++++++++ auth_brute_force/security/ir_model_access.yml | 28 ++++ auth_brute_force/static/description/icon.png | Bin 0 -> 9455 bytes .../description/screenshot_attempts_list.png | Bin 0 -> 29462 bytes .../description/screenshot_custom_ban.png | Bin 0 -> 31984 bytes auth_brute_force/views/action.xml | 39 +++++ auth_brute_force/views/menu.xml | 32 ++++ auth_brute_force/views/view.xml | 98 ++++++++++++ 18 files changed, 893 insertions(+) create mode 100644 auth_brute_force/README.rst create mode 100644 auth_brute_force/__init__.py create mode 100644 auth_brute_force/__openerp__.py create mode 100644 auth_brute_force/controllers/__init__.py create mode 100644 auth_brute_force/controllers/controllers.py create mode 100644 auth_brute_force/data/ir_config_parameter.xml create mode 100644 auth_brute_force/i18n/auth_brute_force.pot create mode 100644 auth_brute_force/i18n/fr.po create mode 100644 auth_brute_force/models/__init__.py create mode 100644 auth_brute_force/models/res_authentication_attempt.py create mode 100644 auth_brute_force/models/res_banned_remote.py create mode 100644 auth_brute_force/security/ir_model_access.yml create mode 100644 auth_brute_force/static/description/icon.png create mode 100644 auth_brute_force/static/description/screenshot_attempts_list.png create mode 100644 auth_brute_force/static/description/screenshot_custom_ban.png create mode 100644 auth_brute_force/views/action.xml create mode 100644 auth_brute_force/views/menu.xml create mode 100644 auth_brute_force/views/view.xml diff --git a/auth_brute_force/README.rst b/auth_brute_force/README.rst new file mode 100644 index 000000000..60b0a73aa --- /dev/null +++ b/auth_brute_force/README.rst @@ -0,0 +1,114 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License + +=============================================================== +Tracks Authentication Attempts and Prevents Brute-force Attacks +=============================================================== + +This module registers each request done by users trying to authenticate into +Odoo. If the authentication fails, a counter is increased for the given remote +IP. After a defined number of attempts, Odoo will ban the remote IP and +ignore new requests. +This module applies security through obscurity +(https://en.wikipedia.org/wiki/Security_through_obscurity), +When a user is banned, the request is now considered as an attack. So, the UI +will **not** indicate to the user that his IP is banned and the regular message +'Wrong login/password' is displayed. + +This module realizes a call to a web API (http://ip-api.com) to try to have +extra information about remote IP. + +Known issue / Roadmap +--------------------- +The ID used to identify a remote request is the IP provided in the request +(key 'REMOTE_ADDR'). +Depending of server and / or user network configuration, the idenfication +of the user can be wrong, and mainly in the following cases: + +* if the Odoo server is behind an Apache / NGinx proxy without redirection, + all the request will be have the value '127.0.0.1' for the REMOTE_ADDR key; +* If some users are behind the same Internet Service Provider, if a user is + banned, all the other users will be banned too; + +Configuration +------------- + +Once installed, you can change the ir.config_parameter value for the key +'auth_brute_force.max_attempt_qty' (10 by default) that define the max number +of attempts allowed before the user was banned. + +Usage +----- + +Admin user have the possibility to unblock a banned IP. + +Logging +------- + +This module generates some WARNING logs, in the three following cases: + +* Authentication failed from remote '127.0.0.1'. Login tried : 'admin'. + Attempt 1 / 10. + +* Authentication failed from remote '127.0.0.1'. The remote has been banned. + Login tried : 'admin'. + +* Authentication tried from remote '127.0.0.1'. The request has been ignored + because the remote has been banned after 10 attempts without success. Login + tried : 'admin'. + +Screenshot +---------- + +**List of Attempts** + +.. image:: /auth_brute_force/static/description/screenshot_attempts_list.png + +**Detail of a banned IP** + +.. image:: /auth_brute_force/static/description/screenshot_custom_ban.png + + +Usage +===== + +* go to ... + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/149/8.0 + +For further information, please visit: + +* https://www.odoo.com/forum/help-1 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback +`here `_. + +Credits +======= + +Contributors +------------ + +* Sylvain LE GAL (https://twitter.com/legalsylvain) + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/auth_brute_force/__init__.py b/auth_brute_force/__init__.py new file mode 100644 index 000000000..b8166bd36 --- /dev/null +++ b/auth_brute_force/__init__.py @@ -0,0 +1,3 @@ +# -*- encoding: utf-8 -*- +from . import models +from . import controllers diff --git a/auth_brute_force/__openerp__.py b/auth_brute_force/__openerp__.py new file mode 100644 index 000000000..b05790164 --- /dev/null +++ b/auth_brute_force/__openerp__.py @@ -0,0 +1,42 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Tracks Authentication Attempts and Prevents Brute-force Attacks module +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Authentification - Brute-force Attack', + 'version': '8.0.1.0.0', + 'category': 'base', + 'summary': "Tracks Authentication Attempts and Prevents Brute-force" + " Attacks module", + 'author': "GRAP,Odoo Community Association (OCA)", + 'website': 'http://www.grap.coop', + 'license': 'AGPL-3', + 'depends': [ + 'web', + ], + 'data': [ + 'security/ir_model_access.yml', + 'data/ir_config_parameter.xml', + 'views/view.xml', + 'views/action.xml', + 'views/menu.xml', + ], +} diff --git a/auth_brute_force/controllers/__init__.py b/auth_brute_force/controllers/__init__.py new file mode 100644 index 000000000..153a9e31e --- /dev/null +++ b/auth_brute_force/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import controllers diff --git a/auth_brute_force/controllers/controllers.py b/auth_brute_force/controllers/controllers.py new file mode 100644 index 000000000..f752eee95 --- /dev/null +++ b/auth_brute_force/controllers/controllers.py @@ -0,0 +1,104 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Tracks Authentication Attempts and Prevents Brute-force Attacks module +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import logging + +from openerp import fields, http, registry, SUPERUSER_ID +from openerp.http import request +from openerp.addons.web.controllers.main import Home, ensure_db + +_logger = logging.getLogger(__name__) + + +class LoginController(Home): + @http.route() + def web_login(self, redirect=None, **kw): + if request.httprequest.method == 'POST': + ensure_db() + remote = request.httprequest.remote_addr + # Get registry and cursor + config_obj = registry(request.session.db)['ir.config_parameter'] + attempt_obj = registry( + request.session.db)['res.authentication.attempt'] + banned_remote_obj = registry( + request.session.db)['res.banned.remote'] + cursor = attempt_obj.pool.cursor() + + # Get Settings + max_attempts_qty = int(config_obj.search_read( + cursor, SUPERUSER_ID, + [('key', '=', 'auth_brute_force.max_attempt_qty')], + ['value'])[0]['value']) + + # Test if remote user is banned + banned = banned_remote_obj.search(cursor, SUPERUSER_ID, [ + ('remote', '=', remote)]) + if banned: + _logger.warning( + "Authentication tried from remote '%s'. The request has" + " been ignored because the remote has been banned after" + " %d attempts without success. Login tried : '%s'." % ( + remote, max_attempts_qty, request.params['login'])) + request.params['password'] = '' + + else: + # Try to authenticate + result = request.session.authenticate( + request.session.db, request.params['login'], + request.params['password']) + + # Log attempt + cursor.commit() + attempt_obj.create(cursor, SUPERUSER_ID, { + 'attempt_date': fields.Datetime.now(), + 'login': request.params['login'], + 'remote': remote, + 'result': banned and 'banned' or ( + result and 'successfull' or 'failed'), + }) + cursor.commit() + if not banned and not result: + # Get last bad attempts quantity + attempts_qty = len(attempt_obj.search_last_failed( + cursor, SUPERUSER_ID, remote)) + + if max_attempts_qty <= attempts_qty: + # We ban the remote + _logger.warning( + "Authentication failed from remote '%s'. " + "The remote has been banned. Login tried : '%s'." % ( + remote, request.params['login'])) + banned_remote_obj.create(cursor, SUPERUSER_ID, { + 'remote': remote, + 'ban_date': fields.Datetime.now(), + }) + cursor.commit() + + else: + _logger.warning( + "Authentication failed from remote '%s'." + " Login tried : '%s'. Attempt %d / %d." % ( + remote, request.params['login'], attempts_qty, + max_attempts_qty)) + cursor.close() + + return super(LoginController, self).web_login(redirect=redirect, **kw) diff --git a/auth_brute_force/data/ir_config_parameter.xml b/auth_brute_force/data/ir_config_parameter.xml new file mode 100644 index 000000000..0eab93cd2 --- /dev/null +++ b/auth_brute_force/data/ir_config_parameter.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + auth_brute_force.max_attempt_qty + 10 + + + + diff --git a/auth_brute_force/i18n/auth_brute_force.pot b/auth_brute_force/i18n/auth_brute_force.pot new file mode 100644 index 000000000..52f9bf6f4 --- /dev/null +++ b/auth_brute_force/i18n/auth_brute_force.pot @@ -0,0 +1,150 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * auth_brute_force +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-09-26 00:39+0000\n" +"PO-Revision-Date: 2015-09-26 00:39+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_banned_remote.py:75 +#, python-format +msgid "%s %s - %s %s (ISP: %s)" +msgstr "" + +#. module: auth_brute_force +#: field:res.banned.remote,active:0 +msgid "Active" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,attempt_date:0 +msgid "Attempt Date" +msgstr "" + +#. module: auth_brute_force +#: model:ir.actions.act_window,name:auth_brute_force.action_res_authentication_attempt +#: model:ir.ui.menu,name:auth_brute_force.menu_res_authentication_attempt +msgid "Authentication Attempts" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,result:0 +msgid "Authentication Result" +msgstr "" + +#. module: auth_brute_force +#: field:res.banned.remote,ban_date:0 +msgid "Ban Date" +msgstr "" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_authentication_attempt.py:34 +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +#: selection:res.authentication.attempt,result:0 +#, python-format +msgid "Banned" +msgstr "" + +#. module: auth_brute_force +#: model:ir.actions.act_window,name:auth_brute_force.action_res_banned_remote +#: model:ir.ui.menu,name:auth_brute_force.menu_res_banned_remote +msgid "Banned Remotes" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,create_uid:0 +#: field:res.banned.remote,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,create_date:0 +#: field:res.banned.remote,create_date:0 +msgid "Created on" +msgstr "" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_authentication_attempt.py:33 +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +#: selection:res.authentication.attempt,result:0 +#, python-format +msgid "Failed" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,id:0 +#: field:res.banned.remote,id:0 +msgid "ID" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,write_uid:0 +#: field:res.banned.remote,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,write_date:0 +#: field:res.banned.remote,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: auth_brute_force +#: field:res.banned.remote,name:0 +msgid "Name" +msgstr "" + +#. module: auth_brute_force +#: field:res.banned.remote,description:0 +msgid "Remote Description" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,remote:0 +#: field:res.banned.remote,remote:0 +msgid "Remote ID" +msgstr "" + +#. module: auth_brute_force +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +msgid "Successful" +msgstr "" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_authentication_attempt.py:32 +#: selection:res.authentication.attempt,result:0 +#, python-format +msgid "Successfull" +msgstr "" + +#. module: auth_brute_force +#: field:res.authentication.attempt,login:0 +msgid "Tried Login" +msgstr "" + +#. module: auth_brute_force +#: help:res.banned.remote,active:0 +msgid "Uncheck this box to unban the remote" +msgstr "" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_banned_remote.py:77 +#, python-format +msgid "Unidentified Call from %s" +msgstr "" + +#. module: auth_brute_force +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +msgid "Without Success" +msgstr "" + diff --git a/auth_brute_force/i18n/fr.po b/auth_brute_force/i18n/fr.po new file mode 100644 index 000000000..7e28872e4 --- /dev/null +++ b/auth_brute_force/i18n/fr.po @@ -0,0 +1,120 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * auth_brute_force +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-09-26 00:34+0000\n" +"PO-Revision-Date: 2015-09-26 00:34+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_banned_remote.py:75 +#, python-format +msgid "%s %s - %s %s (ISP: %s)" +msgstr "%s %s - %s %s (FAI : %s)" + +#. module: auth_brute_force +#: field:res.banned.remote,active:0 +msgid "Active" +msgstr "Active" + +#. module: auth_brute_force +#: field:res.authentication.attempt,attempt_date:0 +msgid "Attempt Date" +msgstr "Date de la tentative" + +#. module: auth_brute_force +#: model:ir.actions.act_window,name:auth_brute_force.action_res_authentication_attempt +#: model:ir.ui.menu,name:auth_brute_force.menu_res_authentication_attempt +msgid "Authentication Attempts" +msgstr "Tentative d'authentification" + +#. module: auth_brute_force +#: field:res.authentication.attempt,result:0 +msgid "Authentication Result" +msgstr "Résultat de l'authentification" + +#. module: auth_brute_force +#: field:res.banned.remote,ban_date:0 +msgid "Ban Date" +msgstr "Ban Date" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_authentication_attempt.py:34 +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +#: selection:res.authentication.attempt,result:0 +#, python-format +msgid "Banned" +msgstr "Banni" + +#. module: auth_brute_force +#: model:ir.actions.act_window,name:auth_brute_force.action_res_banned_remote +#: model:ir.ui.menu,name:auth_brute_force.menu_res_banned_remote +msgid "Banned Remotes" +msgstr "Clients distants bannis" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_authentication_attempt.py:33 +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +#: selection:res.authentication.attempt,result:0 +#, python-format +msgid "Failed" +msgstr "Echoué" + +#. module: auth_brute_force +#: field:res.banned.remote,name:0 +msgid "Name" +msgstr "Nom" + +#. module: auth_brute_force +#: field:res.banned.remote,description:0 +msgid "Description" +msgstr "Description" + +#. module: auth_brute_force +#: field:res.authentication.attempt,remote:0 +#: field:res.banned.remote,remote:0 +msgid "Remote ID" +msgstr "ID du client Distant" + +#. module: auth_brute_force +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +msgid "Successful" +msgstr "Réussie" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_authentication_attempt.py:32 +#: selection:res.authentication.attempt,result:0 +#, python-format +msgid "Successfull" +msgstr "Réussie" + +#. module: auth_brute_force +#: field:res.authentication.attempt,login:0 +msgid "Tried Login" +msgstr "Idenfiant essayé" + +#. module: auth_brute_force +#: help:res.banned.remote,active:0 +msgid "Uncheck this box to unban the remote" +msgstr "Décochez cette case afin d'annuler l'exclusion du client distant" + +#. module: auth_brute_force +#: code:addons/auth_brute_force/models/res_banned_remote.py:77 +#, python-format +msgid "Unidentified Call from %s" +msgstr "Appel non identifié depuis %s" + +#. module: auth_brute_force +#: view:res.authentication.attempt:auth_brute_force.view_res_authentication_attempt_search +msgid "Without Success" +msgstr "Sans succès" + diff --git a/auth_brute_force/models/__init__.py b/auth_brute_force/models/__init__.py new file mode 100644 index 000000000..85cc3145c --- /dev/null +++ b/auth_brute_force/models/__init__.py @@ -0,0 +1,3 @@ +# -*- encoding: utf-8 -*- +from . import res_banned_remote +from . import res_authentication_attempt diff --git a/auth_brute_force/models/res_authentication_attempt.py b/auth_brute_force/models/res_authentication_attempt.py new file mode 100644 index 000000000..84e735bd3 --- /dev/null +++ b/auth_brute_force/models/res_authentication_attempt.py @@ -0,0 +1,58 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Tracks Authentication Attempts and Prevents Brute-force Attacks module +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api +from openerp.tools.translate import _ + + +class ResAuthenticationAttempt(models.Model): + _name = 'res.authentication.attempt' + _order = 'attempt_date desc' + + _ATTEMPT_RESULT = [ + ('successfull', _('Successfull')), + ('failed', _('Failed')), + ('banned', _('Banned')), + ] + + # Column Section + attempt_date = fields.Datetime(string='Attempt Date') + + login = fields.Char(string='Tried Login') + + remote = fields.Char(string='Remote ID') + + result = fields.Selection( + selection=_ATTEMPT_RESULT, string='Authentication Result') + + # Custom Section + @api.model + def search_last_failed(self, remote): + last_ok = self.search( + [('result', '=', 'successfull'), ('remote', '=', remote)], + order='attempt_date desc', limit=1) + if last_ok: + return self.search([ + ('remote', '=', remote), + ('attempt_date', '>', last_ok.attempt_date)]) + else: + return self.search([('remote', '=', remote)]) diff --git a/auth_brute_force/models/res_banned_remote.py b/auth_brute_force/models/res_banned_remote.py new file mode 100644 index 000000000..661dfc8a5 --- /dev/null +++ b/auth_brute_force/models/res_banned_remote.py @@ -0,0 +1,71 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Tracks Authentication Attempts and Prevents Brute-force Attacks module +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import urllib +import json + +from openerp import models, fields, api + + +class ResBannedRemote(models.Model): + _name = 'res.banned.remote' + _rec_name = 'remote' + + _GEOLOCALISATION_URL = "http://ip-api.com/json/{}" + + # Default Section + def _default_ban_date(self): + return fields.Datetime.now() + + # Column Section + description = fields.Text( + string='Description', compute='_compute_description', store=True) + + ban_date = fields.Datetime( + string='Ban Date', required=True, default=_default_ban_date) + + remote = fields.Char(string='Remote ID', required=True) + + active = fields.Boolean( + string='Active', help="Uncheck this box to unban the remote", + default=True) + + attempt_ids = fields.Many2many( + comodel_name='res.authentication.attempt', string='Attempts', + compute='_compute_attempt_ids') + + # Compute Section + @api.multi + @api.depends('remote') + def _compute_description(self): + for item in self: + url = self._GEOLOCALISATION_URL.format(item.remote) + res = json.loads(urllib.urlopen(url).read()) + item.description = '' + for k, v in res.iteritems(): + item.description += '%s : %s\n' % (k, v) + + @api.multi + def _compute_attempt_ids(self): + for item in self: + attempt_obj = self.env['res.authentication.attempt'] + item.attempt_ids = attempt_obj.search_last_failed(item.remote).ids diff --git a/auth_brute_force/security/ir_model_access.yml b/auth_brute_force/security/ir_model_access.yml new file mode 100644 index 000000000..57919b774 --- /dev/null +++ b/auth_brute_force/security/ir_model_access.yml @@ -0,0 +1,28 @@ +# -*- encoding: utf-8 -*- +- !record {model: ir.model.access, id: access_res_authentication_attempt_all}: + model_id: model_res_authentication_attempt + name: Authentication Attempt All Users + perm_read: true + +- !record {model: ir.model.access, id: access_res_banned_remote_all}: + model_id: model_res_banned_remote + name: Banned Remote All Users + perm_read: true + +- !record {model: ir.model.access, id: access_res_authentication_attempt_manager}: + group_id: base.group_system + model_id: model_res_authentication_attempt + name: Authentication Attempt Manager + perm_create: true + perm_read: true + perm_write: true + perm_unlink: true + +- !record {model: ir.model.access, id: access_res_banned_remote_manager}: + group_id: base.group_system + model_id: model_res_banned_remote + name: Banned Remote Manager + perm_create: true + perm_read: true + perm_write: true + perm_unlink: true diff --git a/auth_brute_force/static/description/icon.png b/auth_brute_force/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/auth_brute_force/static/description/screenshot_attempts_list.png b/auth_brute_force/static/description/screenshot_attempts_list.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee6f940fdaca0d7078346c5be66474fcff28269 GIT binary patch literal 29462 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 literal 0 HcmV?d00001 diff --git a/auth_brute_force/views/action.xml b/auth_brute_force/views/action.xml new file mode 100644 index 000000000..7b19a7e90 --- /dev/null +++ b/auth_brute_force/views/action.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + Authentication Attempts + res.authentication.attempt + form + tree,graph + {"search_default_filter_no_success":1} + + + + Banned Remotes + res.banned.remote + form + tree,form + + + + diff --git a/auth_brute_force/views/menu.xml b/auth_brute_force/views/menu.xml new file mode 100644 index 000000000..99661eeb4 --- /dev/null +++ b/auth_brute_force/views/menu.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth_brute_force/views/view.xml b/auth_brute_force/views/view.xml new file mode 100644 index 000000000..7b7de28c3 --- /dev/null +++ b/auth_brute_force/views/view.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + res.authentication.attempt + + + + + + + + + + + + res.authentication.attempt + + + + + + + + + + res.authentication.attempt + + + + + + + + + + + + + + res.banned.remote + + + + + + + + + + + res.banned.remote + +
+ + + + + + + + + +
+
+
+ + + res.banned.remote + + + + + + + +
+