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

[feature] Added intergration with openwisp-monitoring #488

Merged
merged 51 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
3be9af0
[feature] Added intergraion with openwisp-monitoring
pandafy Aug 18, 2023
a6c90c2
[req-changes] Fixed colours for RADIUS charts
pandafy Aug 31, 2023
7afde86
[chores] Refactored code
pandafy Aug 31, 2023
a2915a5
[tests] Added tests for RADIUS monitoring
pandafy Aug 31, 2023
b550fd6
[chores] Updated requirements-test.txt
pandafy Aug 31, 2023
4309d9a
[ci] Added stylelint and jshint
pandafy Aug 31, 2023
8c7fc9e
[tests] Fixed test suite
pandafy Aug 31, 2023
e35dc2e
[ci] Updated system dependencies
pandafy Aug 31, 2023
b547564
[tests] Fixed coverage
pandafy Sep 8, 2023
ff35bdd
[docs] Added documentation
pandafy Sep 8, 2023
48b42fb
[feature] Added dashboard pie charts for radius monitoring
pandafy Sep 13, 2023
f75c919
[docs] Added dashboard pie chart screenshot
pandafy Sep 14, 2023
bc9fe31
[fix] Removed precision from Round() which is not support on Django 3.2
pandafy Sep 30, 2023
fb2cc92
[chores] Upgraded openwisp-utils dependency
pandafy Sep 30, 2023
1dbd84e
[fix] Handle called_station_id uses "-" instead of ":"
pandafy Feb 16, 2024
a5bc4d1
[req-changes] Updated colors for the user registration page
pandafy Mar 8, 2024
8e41e70
[req-changes] Don't discard accounting metrics if related device is n…
pandafy Mar 8, 2024
9da878c
[req-changes] Updated colours
pandafy Mar 12, 2024
76ca1db
[tests] Added test for changes in post_save_radiusaccounting
pandafy Mar 12, 2024
2d06b95
[req-changes] Use a separate metric for storing total registered users
pandafy Mar 14, 2024
52bfbd2
[req-changes] Moved "RADIUS Sessions" tab on the device page after "C…
pandafy Mar 15, 2024
182a690
[change] Create a separate metric and chart for total registered users
pandafy Mar 15, 2024
ea631b8
[tests] Fixed test suite
pandafy Mar 15, 2024
65f7fa9
[change] Updated colours
pandafy Mar 15, 2024
fd4c961
[change] Exclude users in write_user_signup_metrics which registered …
pandafy Mar 15, 2024
848ebdb
[revert] Revert "[change] Updated colours"
pandafy Mar 15, 2024
ff6233e
[change] Added fill operation in influxDB query
pandafy Mar 15, 2024
ab74117
[change] Removed fill from user registration graph
pandafy Mar 18, 2024
0aebaf9
[tests] Fixed tests
pandafy Mar 18, 2024
45798e6
[fix] Fixed called_station_id and calling_station_id lookup for Radiu…
pandafy Mar 19, 2024
8acf9f5
[fix] Fixed view all radius sessions button in device change page
pandafy Mar 19, 2024
d75737c
[fix] Fixed alignment of RADIUS Session text
pandafy Mar 19, 2024
6642ef1
[req-changes] Fixed inconsistencies in UI
pandafy Mar 21, 2024
5c06646
[req-changes] Updated order of RADIUS charts in device page
pandafy Apr 1, 2024
fdfb63f
[req-change] Use verbose label for SAML in radius monitoring charts
pandafy Apr 4, 2024
8760003
[req-change] Use verbose name for all registration methods
pandafy Apr 4, 2024
7cea573
[fix] Fixed date formatting for RADIUS sessions on device page
pandafy Apr 17, 2024
db093e4
[fix] Fixed metric not writing when RegisteredUser does not exist
pandafy Apr 17, 2024
fe973a5
[fix] Fixed test
pandafy Apr 17, 2024
f9e7054
[req-changes] Removed fill from User Registration form
pandafy Apr 18, 2024
e19b726
[req-changes] Renamed labels of RADIUS monitoring charts
pandafy Apr 18, 2024
257c5f4
[change] Hash calling_station_id
pandafy May 6, 2024
9e611c4
[req-changes] Added setting for disable org lookup for device
pandafy May 7, 2024
6b6dbd9
[req-changes] Renamed setting
pandafy May 7, 2024
b00b0ee
[change] Use device.organization_id for RADIUS metric if SHARED_ACCOU…
pandafy May 8, 2024
b360628
[req-change] Don't overwrite the organization of RadiusAccounting
pandafy May 8, 2024
b02c43b
[chores] Removed changes to .gitignore and setup.cfg
pandafy May 13, 2024
edeaa79
[req-changes] Updated docs
pandafy Oct 30, 2024
520efe2
[deps] Updated requirements-test.txt
pandafy Oct 30, 2024
dd9a682
[ci] Fixed docker command
pandafy Oct 30, 2024
36e7b01
[qa] Formatted docs
pandafy Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,23 @@ jobs:
id: deps
run: |
sudo apt update -qq
sudo apt-get -qq -y install xmlsec1 gettext
sudo apt-get -qq -y install xmlsec1 gettext \
sqlite3 \
fping \
gdal-bin \
libproj-dev \
libgeos-dev \
libspatialite-dev \
spatialite-bin \
libsqlite3-mod-spatialite
sudo npm install -g jslint stylelint jshint
pip install -U pip wheel setuptools
pip install -U -r requirements-test.txt
pip install -e .[saml,openvpn_status]
pip install ${{ matrix.django-version }}
sudo npm install -g jslint

- name: Start InfluxDB and Redis container
run: docker compose up -d influxdb redis

- name: QA checks
run: |
Expand All @@ -57,10 +68,11 @@ jobs:
- name: Tests
if: ${{ !cancelled() && steps.deps.conclusion == 'success' }}
run: |
coverage run runtests.py --parallel || ./runtests.py
coverage run --parallel-mode runtests.py --parallel || ./runtests.py
# SAMPLE tests do not influence coverage, so we can speed up tests with --parallel
SAMPLE_APP=1 coverage run ./runtests.py --parallel > /dev/null 2>&1 || SAMPLE_APP=1 ./runtests.py
SAMPLE_APP=1 coverage run --parallel-mode ./runtests.py --parallel > /dev/null 2>&1 || SAMPLE_APP=1 ./runtests.py
coverage combine
MONITORING_INTEGRATION=1 coverage run --append runtests.py
coverage xml

- name: Upload Coverage
Expand Down
7 changes: 7 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"unused": true,
"esversion": 6,
"curly": true,
"strict": "global",
"browser": true
}
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "3"

services:
influxdb:
image: influxdb:1.8-alpine
volumes:
- influxdb-data:/var/lib/influxdb
ports:
- "8086:8086"
environment:
INFLUXDB_DB: openwisp2
INFLUXDB_USER: openwisp
INFLUXDB_USER_PASSWORD: openwisp

redis:
image: redis:alpine
ports:
- "6379:6379"
entrypoint: redis-server --appendonly yes

volumes:
influxdb-data: {}
Binary file added docs/images/radius-dashboard-charts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/radius-traffic-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/total-user-registration-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/unique-radius-session-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/user-registration-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ OpenWISP architecture.
user/saml.rst
user/enforcing_limits.rst
user/change_of_authorization.rst
user/radius_monitoring
user/management_commands.rst
user/rest-api.rst
user/settings.rst
Expand Down
80 changes: 80 additions & 0 deletions docs/user/radius_monitoring.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
.. _integration_with_openwisp_monitoring:

Integration with OpenWISP Monitoring
====================================

OpenWISP RADIUS includes an optional Django sub-app that adds integration
with :doc:`OpenWISP Monitoring </monitoring/index>` to provide RADIUS
metrics.

.. image:: ../images/radius-dashboard-charts.png
:alt: RADIUS session dashboard charts

RADIUS metrics
--------------

1. User registrations
~~~~~~~~~~~~~~~~~~~~~

.. image:: ../images/user-registration-chart.png
:alt: User registration chart

This chart shows number of users signed up using different registration
methods.

2. Total user registrations
~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. image:: ../images/total-user-registration-chart.png
:alt: Total user registration chart

This chart shows total users registered using different registration
methods in the system on a given date.

3. Unique RADIUS Sessions
~~~~~~~~~~~~~~~~~~~~~~~~~

.. image:: ../images/unique-radius-session-chart.png
:alt: Unique RADIUS session chart

This chart shows unique RADIUS sessions. It is helpful to know how many
unique users has used the system in a given time.

4. RADIUS traffic
~~~~~~~~~~~~~~~~~

.. image:: ../images/radius-traffic-chart.png
:alt: RADIUS traffic chart

This chart shows the RADIUS traffic generated by user sessions.

Enabling RADIUS metrics in Django project
-----------------------------------------

.. include:: /partials/settings-note.rst

You can enable the monitoring integration by including
``openwisp_radius.integrations.monitoring`` in ``INSTALLED_APPS`` of your
Django project's settings as following:

.. code-block:: python

# In your_project/settings.py

INSTALLED_APPS.append("openwisp_radius.integrations.monitoring")

.. note::

Ensure your Django project is correctly configured to utilize OpenWISP
Monitoring. For production environments, it is advisable to deploy
OpenWISP using :doc:`Ansible OpenWISP </ansible/index>` or
:doc:`Docker OpenWISP </docker/index>`, as they simplify the
deployment process considerably.

.. important::

If you are registering a :ref:`"registration method"
<openwisp_radius_register_registration_method>` in any other Django
application, then ``openwisp_radius.integrations.monitoring`` should
come after that app in the ``INSTALLED_APPS``. Otherwise, the
registration method would not appear in the chart.
6 changes: 4 additions & 2 deletions docs/user/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,8 @@ If this is enabled, each registered user should be verified using a
verification method. The following choices are available by default:

- ``''`` (empty string): unspecified
- ``manual``: manually created
- ``email``: Email (No Identity Verification)
- ``manual``: Manually created
- ``email``: Email
- ``mobile_phone``: Mobile phone number :ref:`verification via SMS
<openwisp_radius_sms_verification_enabled>`
- ``social_login``: :doc:`social login feature <social_login>`
Expand All @@ -690,6 +690,8 @@ verification method. The following choices are available by default:
**Disclaimer:** these are just suggestions on possible configurations
of OpenWISP RADIUS and must not be considered as legal advice.

.. _openwisp_radius_register_registration_method:

Adding support for more registration/verification methods
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Expand Down
5 changes: 5 additions & 0 deletions openwisp_radius/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def get_api_urls(api_views=None):
api_views.download_rad_batch_pdf,
name='download_rad_batch_pdf',
),
path(
'radius/sessions/',
api_views.radius_accounting,
name='radius_accounting_list',
),
]
else:
return []
47 changes: 46 additions & 1 deletion openwisp_radius/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
from django.contrib.sites.shortcuts import get_current_site
from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.db.utils import IntegrityError
from django.http import Http404, HttpResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.utils.translation.trans_real import get_language_from_request
from django.views.decorators.csrf import csrf_exempt
from django_filters.rest_framework import DjangoFilterBackend
from django_filters.rest_framework import CharFilter, DjangoFilterBackend
from drf_yasg.utils import no_body, swagger_auto_schema
from rest_framework import serializers, status
from rest_framework.authentication import SessionAuthentication
Expand All @@ -41,6 +42,7 @@

from openwisp_radius.api.serializers import RadiusUserSerializer
from openwisp_users.api.authentication import BearerAuthentication, SesameAuthentication
from openwisp_users.api.mixins import FilterByOrganizationManaged, ProtectedAPIMixin
from openwisp_users.api.permissions import IsOrganizationManager
from openwisp_users.api.views import ChangePasswordView as BasePasswordChangeView
from openwisp_users.backends import UsersAuthenticationBackend
Expand Down Expand Up @@ -801,3 +803,46 @@ def create_phone_token(self, *args, **kwargs):


change_phone_number = ChangePhoneNumberView.as_view()


class RadiusAccountingFilter(AccountingFilter):
called_station_id = CharFilter(
field_name='called_station_id', method='filter_mac_address'
)
calling_station_id = CharFilter(
field_name='calling_station_id', method='filter_mac_address'
)

def filter_mac_address(self, queryset, name, value):
"""
The input MAC address in any of these two formats:
- AA-BB-CC-DD-EE-FF (quadrants separated by hyphen)
- AA:BB:CC:DD:EE:FF (quadrants separated by colon)
The below lookup ensures that the filtering is
case-insensitive and works across different formats.
"""
lookup = f'{name}__iexact'
return queryset.filter(
Q(**{lookup: value.replace(':', '-')})
| Q(**{lookup: value.replace('-', ':')})
)


@method_decorator(
name='get',
decorator=swagger_auto_schema(
operation_description="""
Returns all RADIUS sessions of user managed organizations.
""",
),
)
class RadiusAccountingView(ProtectedAPIMixin, FilterByOrganizationManaged, ListAPIView):
throttle_scrope = 'radius_accounting_list'
serializer_class = RadiusAccountingSerializer
pagination_class = AccountingViewPagination
filter_backends = (DjangoFilterBackend,)
filterset_class = RadiusAccountingFilter
queryset = RadiusAccounting.objects.all().order_by('-start_time')


radius_accounting = RadiusAccountingView.as_view()
Empty file.
Empty file.
40 changes: 40 additions & 0 deletions openwisp_radius/integrations/monitoring/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.contrib import admin
from django.urls import reverse
from swapper import load_model

Device = load_model('config', 'Device')
RadiusAccounting = load_model('openwisp_radius', 'RadiusAccounting')

BaseDeviceAdmin = admin.site._registry[Device].__class__


class DeviceAdmin(BaseDeviceAdmin):
change_form_template = 'admin/config/radius-monitoring/device/change_form.html'

class Media:
js = tuple(BaseDeviceAdmin.Media.js) + (
'radius-monitoring/js/device-change.js',
)
css = {
'all': ('radius-monitoring/css/device-change.css',)
+ BaseDeviceAdmin.Media.css['all']
}

def get_extra_context(self, pk=None):
ctx = super().get_extra_context(pk)
ctx.update(
{
'radius_accounting_api_endpoint': reverse(
'radius:radius_accounting_list'
),
'radius_accounting': reverse(
f'admin:{RadiusAccounting._meta.app_label}'
f'_{RadiusAccounting._meta.model_name}_changelist'
),
}
)
return ctx


admin.site.unregister(Device)
admin.site.register(Device, DeviceAdmin)
Loading