show cache on admin overview, add modal to clear cache, re-add logging to policy

This commit is contained in:
Jens Langhammer 2019-04-29 20:37:44 +02:00
parent f576985cc9
commit e0d597eeac
4 changed files with 79 additions and 15 deletions

View file

@ -152,10 +152,8 @@
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="card-pf card-pf-accented card-pf-aggregate-status">
<h2 class="card-pf-title">
<a href="#">
<span class="pficon-bundle"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
</a>
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
@ -192,5 +190,59 @@
</div>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="card-pf card-pf-accented card-pf-aggregate-status">
<h2 class="card-pf-title">
<span class="pficon-server"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Cached Policies' %}
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
<span class="card-pf-aggregate-status-notification">
<a href="#" data-toggle="modal" data-target="#clearCacheMOdal">
{% if cached_policies < 1 %}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No policies cached. Users may experience slow response times.' %}"></span> {{ cached_policies }}
{% else %}
<span class="pficon pficon-ok"></span>{{ cached_policies }}
{% endif %}
</a>
</span>
</p>
</div>
</div>
</div>
</div>
<div class="modal fade" id="clearCacheMOdal" tabindex="-1" role="dialog" aria-labelledby="clearCacheMOdalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="clearCacheMOdalLabel">{% trans 'Clear Cache' %}</h4>
</div>
<div class="modal-body">
<form method="post" id="clearForm">
{% csrf_token %}
<input type="hidden" name="clear">
<p>
{% blocktrans %}
Are you sure you want to clear the cache? This includes all user sessions and all cached Policy results.
{% endblocktrans %}
</p>
<h3>
{% blocktrans %}
This will also log you out.
{% endblocktrans %}
</h3>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button form="clearForm" type="submit" type="button" class="btn btn-danger">{% trans 'Clear' %}</button>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -1,4 +1,6 @@
"""passbook administration overview"""
from django.core.cache import cache
from django.shortcuts import redirect, reverse
from django.views.generic import TemplateView
from passbook.admin.mixins import AdminRequiredMixin
@ -13,6 +15,12 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
template_name = 'administration/overview.html'
def post(self, *args, **kwargs):
if 'clear' in self.request.POST:
cache.clear()
return redirect(reverse('passbook_core:auth-login'))
return self.get(*args, **kwargs)
def get_context_data(self, **kwargs):
kwargs['application_count'] = len(Application.objects.all())
kwargs['policy_count'] = len(Policy.objects.all())
@ -25,4 +33,6 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
kwargs['worker_count'] = len(CELERY_APP.control.ping(timeout=0.5))
kwargs['providers_without_application'] = Provider.objects.filter(application=None)
kwargs['policies_without_attachment'] = len(Policy.objects.filter(policymodel__isnull=True))
kwargs['cached_policies'] = len(cache.keys('policy_*'))
print(cache.keys('*'))
return super().get_context_data(**kwargs)

View file

@ -1,5 +1,6 @@
"""passbook core policy engine"""
# from logging import getLogger
from logging import getLogger
from amqp.exceptions import UnexpectedFrame
from celery import group
from celery.exceptions import TimeoutError as CeleryTimeoutError
@ -9,10 +10,10 @@ from ipware import get_client_ip
from passbook.core.celery import CELERY_APP
from passbook.core.models import Policy, User
# LOGGER = getLogger(__name__)
LOGGER = getLogger(__name__)
def _cache_key(policy, user):
return "%s#%s" % (policy.uuid, user.pk)
return "policy_%s#%s" % (policy.uuid, user.pk)
@CELERY_APP.task()
def _policy_engine_task(user_pk, policy_pk, **kwargs):
@ -23,8 +24,8 @@ def _policy_engine_task(user_pk, policy_pk, **kwargs):
user_obj = User.objects.get(pk=user_pk)
for key, value in kwargs.items():
setattr(user_obj, key, value)
# LOGGER.debug("Running policy `%s`#%s for user %s...", policy_obj.name,
# policy_obj.pk.hex, user_obj)
LOGGER.debug("Running policy `%s`#%s for user %s...", policy_obj.name,
policy_obj.pk.hex, user_obj)
policy_result = policy_obj.passes(user_obj)
# Handle policy result correctly if result, message or just result
message = None
@ -33,10 +34,10 @@ def _policy_engine_task(user_pk, policy_pk, **kwargs):
# Invert result if policy.negate is set
if policy_obj.negate:
policy_result = not policy_result
# LOGGER.debug("Policy %r#%s got %s", policy_obj.name, policy_obj.pk.hex, policy_result)
LOGGER.debug("Policy %r#%s got %s", policy_obj.name, policy_obj.pk.hex, policy_result)
cache_key = _cache_key(policy_obj, user_obj)
cache.set(cache_key, (policy_obj.action, policy_result, message))
# LOGGER.debug("Cached entry as %s", cache_key)
LOGGER.debug("Cached entry as %s", cache_key)
return policy_obj.action, policy_result, message
class PolicyEngine:
@ -81,16 +82,16 @@ class PolicyEngine:
for policy in self.policies:
cached_policy = cache.get(_cache_key(policy, self.__user), None)
if cached_policy:
# LOGGER.debug("Taking result from cache for %s", policy.pk.hex)
LOGGER.debug("Taking result from cache for %s", policy.pk.hex)
cached_policies.append(cached_policy)
else:
# LOGGER.debug("Evaluating policy %s", policy.pk.hex)
LOGGER.debug("Evaluating policy %s", policy.pk.hex)
signatures.append(_policy_engine_task.signature(
args=(self.__user.pk, policy.pk.hex),
kwargs=kwargs,
time_limit=policy.timeout))
self.__get_timeout += policy.timeout
# LOGGER.debug("Set total policy timeout to %r", self.__get_timeout)
LOGGER.debug("Set total policy timeout to %r", self.__get_timeout)
# If all policies are cached, we have an empty list here.
if signatures:
self.__group = group(signatures)()
@ -119,7 +120,7 @@ class PolicyEngine:
for policy_action, policy_result, policy_message in result:
passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \
(policy_action == Policy.ACTION_DENY and not policy_result)
# LOGGER.debug('Action=%s, Result=%r => %r', policy_action, policy_result, passing)
LOGGER.debug('Action=%s, Result=%r => %r', policy_action, policy_result, passing)
if policy_message:
messages.append(policy_message)
if not passing:

View file

@ -2,6 +2,7 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from passbook.core.models import Application
from passbook.core.policies import PolicyEngine