diff --git a/Dockerfile b/Dockerfile index 660ae229..2a2da082 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,6 +43,7 @@ ADD docker/nginx/sal.conf /etc/nginx/sites-enabled/sal.conf ADD docker/nginx/nginx.conf /etc/nginx/nginx.conf ADD docker/settings.py $APP_DIR/sal/ ADD docker/settings_import.py $APP_DIR/sal/ +ADD docker/brute_settings.py $APP_DIR/sal/ ADD docker/wsgi.py $APP_DIR/ ADD docker/gunicorn_config.py $APP_DIR/ ADD docker/django/management/ $APP_DIR/sal/management/ diff --git a/README.md b/README.md index 2ca1548a..2d3a80f4 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,14 @@ You can enable, disable and re-order your plugins from the Settings page, under After re-ordering and hiding plugins from some screens, you might even want to make your own plugins. You can base your plugin off of one of the included ones, or one of mine in the [repository of optional plugins](https://github.com/salopensource/grahamgilbert-plugins). Trust me it's easy if you know python, and completely possible even if you don't. If you want more information on creating your own plugin you can follow a series of posts from my blog [part 1](http://grahamgilbert.com/blog/2014/01/26/writing-plugins-for-sal-part-1/), [part 2](http://grahamgilbert.com/blog/2014/02/07/writing-plugins-for-sal-part-2/), and [part 3](http://grahamgilbert.com/blog/2014/02/17/writing-plugins-for-sal-part-3/). +## Brute force protection + +Sal has built in brute force protection. See it's [documentation](https://github.com/salopensource/sal/blob/master/docs/Settings.md) for more details or if you're using Docker, see how to turn it on in the [Readme](https://github.com/salopensource/sal/blob/master/docker/README.md). + +## LDAP Authentication + +There is a variant of Sal that supports LDAP authenctication. At this time, only using the [sal-ldap Docker image](https://hub.docker.com/r/macadmins/sal-ldap) is supported. + ## Having problems? You should check out the [troubleshooting](https://github.com/salopensource/sal/blob/master/docs/Troubleshooting.md) page. diff --git a/docker/README.md b/docker/README.md index 1ffeae17..e3f469d2 100644 --- a/docker/README.md +++ b/docker/README.md @@ -13,6 +13,9 @@ Several options, such as the timezone and admin password are customizable using * ``DOCKER_SAL_ADMINS``: The admin user's details. Defaults to ``Docker User, docker@localhost``. * ``DOCKER_SAL_DEFAULT_MACHINE_GROUP_KEY``: By default, all machine submissions must include a machine group key otherwise an error will occur. By defining this value to an existing machine group key then machines without a group key already defined in its preferences will be placed into this group. * ``DOCKER_SAL_DEBUG``: Whether debug mode is enabled or not. Valid values are ``true`` and ``false``. Defaults to ``false``. +* ``DOCKER_SAL_BRUTE_PROTECT``: Whether brute force protection mode is enabled or not. Valid values are ``true`` and ``false``. Defaults to ``false``. +* ``DOCKER_SAL_BRUTE_COOLOFF``: Cooloff period after which failed logins will be forgotten. Must be an integer representing the number of hours. Defaults to ``3``. +* ``DOCKER_SAL_BRUTE_LIMIT``: Number of failed login attempts allowed within the timeout period before the account is blocked. Must be an integer. Defaults to ``3``. If you require more advanced settings, for example if you want to hide certain plugins from certain Business Units or if you have a plugin that needs settings, you can override ``settings.py`` with your own. A good starting place can be found on this image's [Github repository](https://github.com/salopensource/sal/blob/master/docker/settings.py). diff --git a/docker/brute_settings.py b/docker/brute_settings.py new file mode 100644 index 00000000..caa007dc --- /dev/null +++ b/docker/brute_settings.py @@ -0,0 +1,6 @@ +############### +INSTALLED_APPS+= ('axes',) +MIDDLEWARE_CLASSES+=('axes.middleware.FailedLoginMiddleware',) +# Max number of login attemts within the ``AXES_COOLOFF_TIME`` +AXES_LOGIN_FAILURE_LIMIT = BRUTE_LIMIT +AXES_COOLOFF_TIME=BRUTE_COOLOFF \ No newline at end of file diff --git a/docker/settings.py b/docker/settings.py index 13f34a13..2d5ac9ab 100644 --- a/docker/settings.py +++ b/docker/settings.py @@ -1,6 +1,9 @@ # Django settings for sal project. from system_settings import * -from settings_import import ADMINS, TIME_ZONE, LANGUAGE_CODE, ALLOWED_HOSTS, DISPLAY_NAME, DEFAULT_MACHINE_GROUP_KEY,DEBUG +from settings_import import ADMINS, TIME_ZONE, LANGUAGE_CODE, ALLOWED_HOSTS, DISPLAY_NAME, DEFAULT_MACHINE_GROUP_KEY,DEBUG, BRUTE_PROTECT, BRUTE_COOLOFF, BRUTE_LIMIT + +if BRUTE_PROTECT == True: + import brute_settings DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. diff --git a/docker/settings_import.py b/docker/settings_import.py index 0a84cf15..1997966d 100644 --- a/docker/settings_import.py +++ b/docker/settings_import.py @@ -11,6 +11,27 @@ except: DEBUG = False +# Read the Brute force protection setting from env var +try: + if getenv('DOCKER_SAL_BRUTE_PROTECT').lower() == 'true': + BRUTE_PROTECT = True + else: + BRUTE_PROTECT = False +except: + BRUTE_PROTECT = False + +# Read the Brute force protection timeout setting from env var +try: + BRUTE_COOLOFF = int(getenv('DOCKER_SAL_BRUTE_COOLOFF')) +except: + BRUTE_COOLOFF = 3 + +# Read the Brute force protection limit setting from env var +try: + BRUTE_LIMIT = int(getenv('DOCKER_SAL_BRUTE_LIMIT')) +except: + BRUTE_LIMIT = 3 + # Read list of admins from $DOCKER_SAL_ADMINS env var admin_list = [] if getenv('DOCKER_SAL_ADMINS'): diff --git a/docs/Settings.md b/docs/Settings.md index 78a0ccaa..d74a5a39 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -2,6 +2,22 @@ By modifying ``sal/settings.py`` you can customise how plugins and data is displayed in Sal. If you are upgrading from a previous version of Sal, refer to this document to see how your ``settings.py`` file should be changed to take advantage of any new features. There are defaults set in ``sal/system_settings.py``, but they can be overridden if you choose. +## Enabling brute force protection + +You can add the following to your ``sal/settings.py`` to enable brute force protection. Change ``BRUTE_LIMIT`` to the number of login attempts allowed before the account is locked, ``BRUTE_COOLOFF`` is the time after which any locked accounts will be unlocked. ``BRUTE_PROTECT`` **must** be set to ``True`` to enable the unlocking UI in the user management page. + +```python +BRUTE_PROTECT = True +BRUTE_COOLOFF = 3 +BRUTE_LIMIT = 3 +############### +INSTALLED_APPS+= ('axes',) +MIDDLEWARE_CLASSES+=('axes.middleware.FailedLoginMiddleware',) +# Max number of login attemts within the ``AXES_COOLOFF_TIME`` +AXES_LOGIN_FAILURE_LIMIT = BRUTE_LIMIT +AXES_COOLOFF_TIME=BRUTE_COOLOFF +``` + ## LIMIT_PLUGIN_TO_FRONT_PAGE These plugins will only be shown on the front page. They will not appear anywhere else. diff --git a/sal/system_settings.py b/sal/system_settings.py index 1204332c..13a0b59f 100644 --- a/sal/system_settings.py +++ b/sal/system_settings.py @@ -2,6 +2,9 @@ DEBUG = False TEMPLATE_DEBUG = DEBUG APPEND_SLASH=True +BRUTE_PROTECT = False +BRUTE_COOLOFF = 3 +BRUTE_LIMIT = 3 PROJECT_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir)) ADMINS = ( # ('Your Name', 'your_email@example.com'), @@ -226,4 +229,4 @@ SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # Allow all host headers - ALLOWED_HOSTS = ['*'] + ALLOWED_HOSTS = ['*'] \ No newline at end of file diff --git a/sal/urls.py b/sal/urls.py index d378a7d1..09072024 100644 --- a/sal/urls.py +++ b/sal/urls.py @@ -8,6 +8,7 @@ urlpatterns = patterns('', # Examples: + url(r'^login$', 'django.contrib.auth.views.login'), url(r'^login/$', 'django.contrib.auth.views.login'), url(r'^logout/$', 'django.contrib.auth.views.logout_then_login'), url(r'^changepassword/$', 'django.contrib.auth.views.password_change', name='password_change'), diff --git a/setup/requirements.txt b/setup/requirements.txt index ee81b8fa..91ff9352 100644 --- a/setup/requirements.txt +++ b/setup/requirements.txt @@ -19,4 +19,5 @@ urllib3==1.10 wsgiref==0.1.2 djangorestframework==3.1.3 python-memcached==1.57 -unicodecsv==0.14.1 \ No newline at end of file +unicodecsv==0.14.1 +django-axes==1.5.0 \ No newline at end of file