Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add note about regular session cleanup to installation instructions #4119

Closed
netsandbox opened this issue Feb 7, 2020 · 14 comments
Closed
Assignees
Labels
status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application

Comments

@netsandbox
Copy link
Contributor

netsandbox commented Feb 7, 2020

Change Type

[ x] Addition
[ ] Correction
[ ] Deprecation
[ ] Cleanup (formatting, typos, etc.)

Area

[ x] Installation instructions
[ ] Configuration parameters
[ ] Functionality/features
[ ] REST API
[ ] Administration/development
[ ] Other

Proposed Changes

Django doesn't clean-up sessions by themself, but provides a command to do so:
https://docs.djangoproject.com/en/2.2/topics/http/sessions/#clearing-the-session-store

Maybe it is worth to add a short note to the installation instructions to setup a daily cronjob for this:

echo -e '#!/bin/sh\npython3 /opt/netbox/netbox/manage.py clearsessions' > /etc/cron.daily/netbox-clearsessions
chmod +x /etc/cron.daily/netbox-clearsessions
@kobayashi
Copy link
Contributor

This may be worth to add in Administration Section of netbox docs.

@kobayashi kobayashi added status: under review Further discussion is needed to determine this issue's scope and/or implementation type: documentation A change or addition to the documentation labels Feb 10, 2020
@hSaria
Copy link
Contributor

hSaria commented Feb 10, 2020

Might be better to implement this in NetBox instead of adding another thing to be maintained by the user. I personally don't see an issue in having it run on every login considering it's a single query and web logins are generally few and far between. Or maybe even doing it in background.

The clearsessions command calls

engine = import_module(settings.SESSION_ENGINE)
try:
    engine.SessionStore.clear_expired()
except NotImplementedError:
    self.stderr.write("Session engine '%s' doesn't support clearing "
                      "expired sessions.\n" % settings.SESSION_ENGINE)

@netsandbox
Copy link
Contributor Author

I don't think that it makes sense to run on every login because:

  1. clearsessions works only for file and database sessions and the user maybe use another session engine
  2. if LOGIN_TIMEOUTis > one day (default is 14 days) it doesn't make sense to run clearsessions more than once a day, which can happen if a user login and logout multiple times a day
  3. this would slow down the login (clearsessions needs on my host 2 seconds)

@hSaria
Copy link
Contributor

hSaria commented Feb 11, 2020

clearsessions works only for file and database sessions and the user maybe use another session engine

This is why the clearsessions already catches NotImplementedError.

if LOGIN_TIMEOUTis > one day (default is 14 days) it doesn't make sense to run clearsessions more than once a day, which can happen if a user login and logout multiple times a day

True, which is why I also suggested an alternative solution of "doing it in background."

this would slow down the login (clearsessions needs on my host 2 seconds)

It takes 2 seconds because every time you run a command through manage.py, it will load the modules and perform any other initialization tasks (e.g. checks on settings, connecting to db, etc...). In runtime, this near instantaneous (it's a single DB call or os.listdir + session.load per session).

I just dislike the idea of throwing more things at the user; the installation steps for a bare setup are already plenty long.

Edit: Performing this at logout is yet another way of doing it while minimizing the effects of login (you usually login more often than logout). Here's the logout diff, but doing it at login is just as fine.

diff --git a/netbox/users/views.py b/netbox/users/views.py
index 6a241027..bf5449f7 100644
--- a/netbox/users/views.py
+++ b/netbox/users/views.py
@@ -11,6 +11,7 @@ from django.utils.decorators import method_decorator
 from django.utils.http import is_safe_url
 from django.views.decorators.debug import sensitive_post_parameters
 from django.views.generic import View
+from importlib import import_module
 
 from secrets.forms import UserKeyForm
 from secrets.models import SessionKey, UserKey
@@ -74,6 +75,13 @@ class LogoutView(View):
         response = HttpResponseRedirect(reverse('home'))
         response.delete_cookie('session_key')
 
+        # Remove any expired sessions
+        engine = import_module(settings.SESSION_ENGINE)
+        try:
+            engine.SessionStore.clear_expired()
+        except NotImplementedError:
+            pass
+
         return response

@kobayashi
Copy link
Contributor

IMO, it is better to leave session store as user preference. Some users want to keep clean session store, but other may not. If this would be implemented in netbox itself, that should be optional. In any case, documentation is required.

@jeremystretch
Copy link
Member

This brings to mind an unrelated but similar task that we currently handle in middleware: The deletion of expired ObjectChange records. Maybe it makes sense to establish a "housekeeping" management command that can be invoked via a cron task to handle these tasks and any other routine maintenance.

It might also be possible to do something clever using a Redis queue to handle running the task. Not sure what the catalyst would be to enqueue the job though.

@hSaria
Copy link
Contributor

hSaria commented Feb 13, 2020

Maybe it makes sense to establish a "housekeeping" management command that can be invoked via a cron task to handle these tasks and any other routine maintenance.

I would personally avoid giving the user access to those things because some may excessively use it or, even worse, use it as a temporary remediation task. If it's something that can be coded internally, then let the software handle itself.

It might also be possible to do something clever using a Redis queue to handle running the task. Not sure what the catalyst would be to enqueue the job though.

Considering a login generates the row, maybe that could be the trigger?

@jeremystretch
Copy link
Member

jeremystretch commented Feb 13, 2020

I should clarify: by "any other routine maintenance," I mean any other built-in tasks that we identify in the future, not something that would be configurable by the end user. The management command would be idempotent, simply deleting any applicable records upon each execution, so there's no danger of a user running it "excessively."

@DanSheps
Copy link
Member

Instead of Cron, could we queue these with rq?

@jeremystretch
Copy link
Member

@DanSheps Yeah, that's what I was getting at. We'd still need a way to trigger the initial queuing of the job though.

@DanSheps
Copy link
Member

What about a like you said, a management command but also an API endpoint and a configurable option in settings on when to run, give people 3 different options so they can choose what is best?

@tyler-8
Copy link
Contributor

tyler-8 commented Feb 25, 2020

The best way to approach this is to move session handling to a cache - it's already self-invalidating and doesn't require any regular maintenance to clean up old sessions.

And since redis is now mandatory, we should have all the dependencies we need to customize this

The Django docs even suggest a cache-based session mechanism as the ideal over both database and file.

@jeremystretch
Copy link
Member

This isn't a strong case for introducing the cache backend when a simple solution (the built-in clearsessions command) already exists. I'd rather not invite new problems while solving a very minimal one. Carrying even a few thousand stale sessions in the database has such a negligible impact on performance I think we'd be fine just calling clearsessions in the upgrade script.

@jeremystretch jeremystretch self-assigned this Mar 4, 2020
@jeremystretch jeremystretch added status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application and removed status: under review Further discussion is needed to determine this issue's scope and/or implementation type: documentation A change or addition to the documentation labels Mar 4, 2020
@jeremystretch
Copy link
Member

I've added the command manage.py clearsessions to the upgrade script and made a note of it in the documentation.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application
Projects
None yet
Development

No branches or pull requests

6 participants