From: Nick Porter Date: Mon, 21 Apr 2025 18:36:51 +0000 (+0100) Subject: Re-write rlm_python howto X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee085b3ac9e303ba1aec500c7191b6071fc846c1;p=thirdparty%2Ffreeradius-server.git Re-write rlm_python howto --- diff --git a/doc/antora/modules/howto/pages/modules/python/index.adoc b/doc/antora/modules/howto/pages/modules/python/index.adoc index 18ea7796018..6bebde2406f 100644 --- a/doc/antora/modules/howto/pages/modules/python/index.adoc +++ b/doc/antora/modules/howto/pages/modules/python/index.adoc @@ -1,70 +1,128 @@ -= rlm_python += Python +== Introduction -Python module for freeradius Copyright 2002 Miguel A Paraz -mailto:mparaz@mparaz.com[mparaz@mparaz.com] Copyright 2002 -Imperium Technology, Inc. +FreeRADIUS can call Python scripts in order to utilize third party libraries +which are only available in Python, or to execute particularly complex +policy. -== Topics +Requires Python 3.8 or later -PURPOSE: To allow module writers to write modules in a high-level -language, for implementation or for prototyping. +== Global configuration -REQUIRES: Python - tested with 2.2 +Due to limitations in Python, the search path for modules can only be +set globally, rather than per module instance. -BUILDING: ./configure –with-experimental-modules +This is set in the Python xref:reference:raddb/global.d/python.adoc[global config]. -USAGE: Make your module available to the Python interpreter by either -putting it in a standard location, or `EXPORT PYTHONPATH=$location'. +== Module configuration -BUGS: 1. Can’t compile statically (./configure –enable-shared=no) - -causes SIGSEGV on the first malloc() in main(). +Each `rlm_python` module xref:reference:raddb/mods-available/python.adoc[instance] +should set a `module` option which is the default Python module from which functions +will be called. -Design: 1. Support for all module functions. 2. One module per function -allowed, for example, from experimental.conf: +An `instantiate` and `detach` function can be defined to run code during server +start up and shutdown. + +When `rlm_python` is called in a processing section, by default the function +called is based on the section name. e.g. if the call is made in `recv Access-Request` +then, `recv_access_request` will be called if it exists, otherwise `recv` will +be called. + +In order to override the function being called, configuration options such as +`func_recv_access_request` or `func_recv` can be used. e.g. ``` -python { - mod_instantiate = radiusd_test - func_instantiate = instantiate +func_recv_access_request = authorize +``` + +could be used to use previous function names. - mod_authorize = radiusd_test - func_authorize = authorize +In addition, the Python module can be changed on a per function basis with +configuration options such as `mod_recv_access_request` or `mod_recv`. - mod_accounting = radiusd_test - func_accounting = accounting +If `rlm_python` is called with a suffix, e.g. - mod_preacct = radiusd_test - func_preacct = preacct +``` +python.my_function +``` - mod_detach = radiusd_test - func_detach = detach +then, by default `my_function` will be called in the default module. As with +other calls the module can be specified with `mod_my_function` and the actual +function with `func_my_function`. + +== Python function behaviour + +Each function is called with an object representing the request, which contains +objects representing the attribute lists. + +Attributes can be accessed using Python dict syntax, e.g. `p.request['User-Name']` +which is an object representing that attribute. + +When an attribute is referenced in string context (e.g. wrapped in `str()`) then +the string representation of the attribute value will be returned. + +Each attribute object has a `value` which can be used to get or set its value in +the appropriate native Python type based on the type of the attribute in the +dictionary e.g. -} ``` +p.reply['Class'].value = b'abc' +``` + +If functions returns None (plain `return' no return), this is treated as `ok`. -* Different functions are wrappers around the same core. -* `func_detach` is passed no parameters, returns module return value. -* If functions returns None (plain `return' no return), default to -RLM_OK -* Python instantiation function can return -1 to signal failure and abort +Specific return codes can be accessed with pre-defined constants in the +`freeradius` module. e.g. + +``` +return freeradius.RLM_MODULE_UPDATED +``` + +The Python `instantiation` function can return -1 to signal failure and abort startup. -Available to module: +== `freeradius` Python module + +FreeRADIUS provides a module, `freeradius`, which can be used by any +Python scripts used by `rlm_python`. + +This module provides: + +=== Constants + +Constants are provided for return codes and log level. + +The return code constants are all of the form `freeradius.RLM_MODULE_` e.g. +`freeradius.RLM_MODULE_OK`. Log level constants are of the form `freeradius.L_` +e.g. `freeradius.L_DBG`. + +In addition, if the module config contains a `config` subsection, that is +parsed to form a dictionary e.g. + +``` +config { + name = "value" +} +``` + +will result in `freeradius.config['name']` having the vaule `value`. + +=== Function + +The function `freeradius.log()` can be called to write log messages via the +FreeRADIUS logging mechanisms. ``` -import radiusd -radiusd.rad_log(radiusd.L_XXX, message_string) -radiusd.RLM_XXX +import freeradius +freeradius.log(message_string, freeradius.L_XXX) ``` -== TODO +Its arguments are: -1. Do we need to support other pair operations beyond set (:=) ? -2. Should we pass the value pair info as a dict and not a tuple? Faster? -3. Give access to more radiusd variables like the dictionary. 3. Give -access to other C functions. Let the Python module deal with the -structures directly, instead of letting our C code do it afterwards. -What’s a good way to represent this? + * The message to log + * (optional) log type (e.g. freeradius.L_DBG) + * (optional) log level - the FreeRADIUS debug level at which this message + should be logged. (e.g. L_DBG_LVL_2) // Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0. // This documentation was developed by Network RADIUS SAS.