From 4c84d400a800c9867ddb2f28c3187b4aea93efac Mon Sep 17 00:00:00 2001 From: adamscmRH Date: Wed, 27 Jun 2018 15:16:07 -0400 Subject: [PATCH] migrate session length setting --- awx/api/conf.py | 8 +-- awx/conf/fields.py | 8 --- .../0005_v330_rename_two_session_settings.py | 62 +++++++++++++++++++ awx/settings/defaults.py | 3 +- .../system-form/sub-forms/system-misc.form.js | 4 +- docs/CHANGELOG.md | 4 +- docs/auth/session.md | 4 +- 7 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 awx/conf/migrations/0005_v330_rename_two_session_settings.py diff --git a/awx/api/conf.py b/awx/api/conf.py index c4c18f7cc4..58aa9b4cc8 100644 --- a/awx/api/conf.py +++ b/awx/api/conf.py @@ -5,20 +5,18 @@ from django.utils.translation import ugettext_lazy as _ from awx.conf import fields, register from awx.api.fields import OAuth2ProviderField from oauth2_provider.settings import oauth2_settings -from django.conf import settings + register( - 'AUTH_TOKEN_EXPIRATION', - field_class=fields.AuthTokenField, + 'SESSION_COOKIE_AGE', + field_class=fields.IntegerField, min_value=60, max_value=30000000000, # approx 1,000 years, higher values give OverflowError - default={'AUTH_TOKEN_EXPIRATION': settings.AUTH_TOKEN_EXPIRATION}, label=_('Idle Time Force Log Out'), help_text=_('Number of seconds that a user is inactive before they will need to login again.'), category=_('Authentication'), category_slug='authentication', ) - register( 'SESSIONS_PER_USER', field_class=fields.IntegerField, diff --git a/awx/conf/fields.py b/awx/conf/fields.py index 582499e351..b98b925447 100644 --- a/awx/conf/fields.py +++ b/awx/conf/fields.py @@ -6,7 +6,6 @@ from collections import OrderedDict # Django from django.core.validators import URLValidator from django.utils.translation import ugettext_lazy as _ -from django.conf import settings # Django REST Framework from rest_framework.fields import * # noqa @@ -43,13 +42,6 @@ class IntegerField(IntegerField): if ret == '' and self.allow_null and not getattr(self, 'allow_blank', False): return None return ret - - -class AuthTokenField(IntegerField): - - def to_internal_value(self, data): - settings.SESSION_COOKIE_AGE = data - return super(AuthTokenField, self).to_internal_value(data) class StringListField(ListField): diff --git a/awx/conf/migrations/0005_v330_rename_two_session_settings.py b/awx/conf/migrations/0005_v330_rename_two_session_settings.py new file mode 100644 index 0000000000..21eecfb556 --- /dev/null +++ b/awx/conf/migrations/0005_v330_rename_two_session_settings.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.utils import timezone +from django.db import migrations + + +def copy_session_settings(apps, schema_editor): + + + def rename_setting(old_key, new_key): + Setting = apps.get_model('conf', 'Setting') + + if Setting.objects.filter(key=new_key).exists(): + logger.error('Setting', new_key, 'unexpectedly exists before this migration, \ + it will be replaced by the value of the', AUTH_TOKEN_EXPIRATION, 'setting.') + + + + + Setting = apps.get_model('conf', 'Setting') + + mapping = { + 'AUTH_TOKEN_EXPIRATION': 'SESSION_COOKIE_AGE', + 'AUTH_TOKEN_PER_USER': 'SESSIONS_PER_USER' +} +for before, after in mapping.items(): + ... + + + for setting_name in mapping: + old_setting = Setting.objects.filter(key=setting_name).first() + if + + if Setting.objects.filter(key='SESSION_COOKIE_AGE').exists(): + logger.error('Setting SESSION_COOKIE_AGE unexpectedly exists before this migration, it will be replaced by AUTH_TOKEN_EXPIRATION setting') + + + if Setting.objects.filter(key='AUTH_TOKEN_EXPIRATION').exists(): + Setting.objects.filter(key='SESSION_COOKIE_AGE').delete() + Setting.objects.get_or_create(key='SESSION_COOKIE_AGE', + value=Setting.objects.get(key='AUTH_TOKEN_EXPIRATION').value, + created=timezone.now(), + modified=timezone.now()) + + if Setting.objects.filter(key='AUTH_TOKEN_PER_USER').exists(): + Setting.objects.filter(key='SESSIONS_PER_USER').delete() + Setting.objects.get_or_create(key='SESSIONS_PER_USER', + value=Setting.objects.get(key='AUTH_TOKEN_PER_USER').value, + created=timezone.now(), + modified=timezone.now()) + + +class Migration(migrations.Migration): + + dependencies = [ + ('conf', '0004_v320_reencrypt'), + ] + + operations = [ + migrations.RunPython(copy_session_settings), + ] + \ No newline at end of file diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 5c09d4daf6..6d1374fa6e 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -200,8 +200,7 @@ SESSION_COOKIE_SECURE = True # Seconds before sessions expire. # Note: This setting may be overridden by database settings. -AUTH_TOKEN_EXPIRATION = 1800 -SESSION_COOKIE_AGE = AUTH_TOKEN_EXPIRATION +SESSION_COOKIE_AGE = 1800 # Maximum number of per-user valid, concurrent sessions. # -1 is unlimited diff --git a/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js b/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js index 2920e8f7e0..02b71edaec 100644 --- a/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js +++ b/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js @@ -24,11 +24,11 @@ export default ['i18n', function(i18n) { MANAGE_ORGANIZATION_AUTH: { type: 'toggleSwitch', }, - AUTH_TOKEN_EXPIRATION: { + SESSION_COOKIE_AGE: { type: 'number', integer: true, min: 60, - reset: 'AUTH_TOKEN_EXPIRATION', + reset: 'SESSION_COOKIE_AGE', }, SESSIONS_PER_USER: { type: 'number', diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 6698f04a60..db33422427 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -49,7 +49,7 @@ * Impose stricter criteria to admin users - organization admin role now necessary for all organizations target user is member of. * Remove unused `admin_role` associated with users. -* Enforce max value for `AUTH_TIMEOUT_EXPIRATION` +* Enforce max value for `SESSION_COOKIE_AGE` [[#1651](https://github.com/ansible/awx/issues/1651)]. * Add stricter validation to `order_by` query params [[#776](https://github.com/ansible/awx/issues/776)]. @@ -71,6 +71,8 @@ * Implemented OAuth2 support for token based authentication [[#21](https://github.com/ansible/awx/issues/21)]. * Added the ability to forcibly expire sessions through `awx-manage expire_sessions`. * Disallowed using HTTP PUT/PATCH methods to modify existing jobs in Job Details API endpoint. +* Changed the name of the session length setting from `AUTH_TOKEN_EXPIRATION` to `SESSION_COOKIE_AGE`. +* Changed the name of the session length setting from `AUTH_TOKEN_PER_USER` to `SESSIONS_PER_USER`. 3.2.0 ===== diff --git a/docs/auth/session.md b/docs/auth/session.md index bc19f53f31..1e31375adc 100644 --- a/docs/auth/session.md +++ b/docs/auth/session.md @@ -45,7 +45,7 @@ Any client should follow the standard rules of [cookie protocol](https://tools.i parse that header to obtain information about the session, such as session cookie name (`session_id`), session cookie value, expiration date, duration, etc. -The duration of the cookie is configurable by Tower Configuration setting `AUTH_TOKEN_EXPIRATION` under +The duration of the cookie is configurable by Tower Configuration setting `SESSION_COOKIE_AGE` under category `authentication`. It is an integer denoting the number of seconds the session cookie should live. The default session cookie age is 2 weeks. @@ -76,7 +76,7 @@ is updated, all sessions she owned will be invalidated and deleted. * User should be able to log in via `/api/login/` endpoint by correctly providing all necessary fields. * Logged in users should be able to authenticate themselves by providing correct session auth info. * Logged in users should be able to log out via `/api/logout/`. -* The duration of a session cookie should be configurable by `AUTH_TOKEN_EXPIRATION`. +* The duration of a session cookie should be configurable by `SESSION_COOKIE_AGE`. * The maximum number of concurrent login for one user should be configurable by `SESSIONS_PER_USER`, and over-limit user sessions should be warned by websocket. * When a user's password is changed, all her sessions should be invalidated and deleted.