3 Commits
Author SHA1 Message Date
gitea_admin b1c569ef72 feat(freeradius): add PostgreSQL support and release 2.0.0
- add separate MySQL and PostgreSQL query configurations
- fix radpostauth INSERT query for PostgreSQL
- remove obsolete pass column from post-auth query
- update ConfigMap and Deployment templates
- bump chart version to 2.0.0
2026-09-07 20:34:42 +02:00
gitea_admin eeeb230b2b upgrade version to 1.0.13 2026-08-04 12:28:40 +02:00
gitea_admin 41834f6ab4 feat(helm): migrate chart dependency to Gitea OCI registry 2026-07-31 10:42:28 +02:00
8 changed files with 777 additions and 12 deletions
+1 -2
View File
@@ -8,7 +8,7 @@ stages:
variables: variables:
CHART_NAME: "freeradius" CHART_NAME: "freeradius"
CHART_VERSION: "1.0.12" CHART_VERSION: "2.0.0"
PACKAGE_PATH: "packages" PACKAGE_PATH: "packages"
ST_COMMON_PROJECT_ID: "270" ST_COMMON_PROJECT_ID: "270"
COMMON_PROJECT_URL: "${CI_API_V4_URL}/projects/${ST_COMMON_PROJECT_ID}/packages/helm/stable" COMMON_PROJECT_URL: "${CI_API_V4_URL}/projects/${ST_COMMON_PROJECT_ID}/packages/helm/stable"
@@ -55,7 +55,6 @@ push_chart_to_gitea:
script: script:
- echo "$GITEA_PASSWORD" | helm registry login $GITEA_URL --username $GITEA_USERNAME --password-stdin - echo "$GITEA_PASSWORD" | helm registry login $GITEA_URL --username $GITEA_USERNAME --password-stdin
- helm push ${PACKAGE_PATH}/${CHART_NAME}-${CHART_VERSION}.tgz $GITEA_REPO - helm push ${PACKAGE_PATH}/${CHART_NAME}-${CHART_VERSION}.tgz $GITEA_REPO
when: manual
only: only:
- main - main
dependencies: dependencies:
+3 -3
View File
@@ -1,6 +1,6 @@
dependencies: dependencies:
- name: st-common - name: st-common
repository: https://gitlab/api/v4/projects/270/packages/helm/stable repository: oci://gitea.infrastructure.helmholz.cloud/gitea_admin/helm
version: 0.1.12 version: 0.1.12
digest: sha256:effc27041fec14dd47ce67b96daae936455482afe0a2d3d6069ebffd7e33ba2c digest: sha256:9087809c86edc369e5d169ea3fd4dbded039b243b50af7b9df18c4b6f168257f
generated: "2026-02-03T12:45:51.347388527+01:00" generated: "2026-07-31T10:36:14.679991115+02:00"
+2 -2
View File
@@ -4,7 +4,7 @@ apiVersion: v2
appVersion: 3.2.7 appVersion: 3.2.7
dependencies: dependencies:
- name: st-common - name: st-common
repository: https://gitlab/api/v4/projects/270/packages/helm/stable repository: oci://gitea.infrastructure.helmholz.cloud/gitea_admin/helm
version: 0.1.12 version: 0.1.12
description: FreeRADIUS is a modular, high performance free RADIUS suite developed description: FreeRADIUS is a modular, high performance free RADIUS suite developed
and distributed under the GNU General Public License, version 2, and is free for and distributed under the GNU General Public License, version 2, and is free for
@@ -27,4 +27,4 @@ sources:
- https://freeradius.org/ - https://freeradius.org/
- https://github.com/FreeRADIUS/freeradius-server - https://github.com/FreeRADIUS/freeradius-server
type: application type: application
version: 1.0.12 version: 2.0.0
+741
View File
@@ -0,0 +1,741 @@
# -*- text -*-
#
# main/postgresql/queries.conf -- PostgreSQL configuration for default schema (schema.sql)
#
# $Id: 80953e0c4e5577a4eeeb3dd98e73a967eb38f52e $
# Use the driver specific SQL escape method.
#
# If you enable this configuration item, the "safe_characters"
# configuration is ignored. FreeRADIUS then uses the PostgreSQL escape
# functions to escape input strings. The only downside to making this
# change is that the PostgreSQL escaping method is not the same the one
# used by FreeRADIUS. So characters which are NOT in the
# "safe_characters" list will now be stored differently in the database.
#
#auto_escape = yes
# Safe characters list for sql queries. Everything else is replaced
# with their mime-encoded equivalents.
# The default list should be ok
# Using 'auto_escape' is preferred
# safe_characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
#######################################################################
# Query config: Username
#######################################################################
# This is the username that will get substituted, escaped, and added
# as attribute 'SQL-User-Name'. '%{SQL-User-Name}' should be used
# below everywhere a username substitution is needed so you you can
# be sure the username passed from the client is escaped properly.
#
# Uncomment the next line, if you want the sql_user_name to mean:
#
# Use Stripped-User-Name, if it's there.
# Else use User-Name, if it's there,
# Else use hard-coded string "none" as the user name.
#
#sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}"
sql_user_name = "%{User-Name}"
#######################################################################
# Query config: Event-Timestamp
#######################################################################
# event_timestamp_epoch is the basis for the time inserted into
# accounting records. Typically this will be the Event-Timestamp of the
# accounting request, which is usually provided by a NAS.
#
# Uncomment the next line, if you want the timestamp to be based on the
# request reception time recorded by this server, for example if you
# distrust the provided Event-Timestamp.
#event_timestamp_epoch = "%l"
event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}"
# event_timestamp is the SQL snippet for converting an epoch timestamp
# to an SQL date.
event_timestamp = "TO_TIMESTAMP(${event_timestamp_epoch})"
#######################################################################
# Query config: Class attribute
#######################################################################
#
# 3.0.22 and later have a "class" column in the accounting table.
#
# However, we do NOT want to break existing configurations by adding
# the Class attribute to the default queries. If we did that, then
# systems using newer versions of the server would fail, because
# there is no "class" column in their accounting tables.
#
# The solution to that is the following "class" subsection. If your
# database has a "class" column for the various tables, then you can
# uncomment the configuration items here. The queries below will
# then automatically insert the Class attribute into radacct,
# radpostauth, etc.
#
class {
#
# Delete the '#' character from each of the configuration
# items in this section. This change puts the Class
# attribute into the various tables. Leave the double-quoted
# string there, as the value for the configuration item.
#
# See also policy.d/accounting, and the "insert_acct_class"
# policy. You will need to list (or uncomment)
# "insert_acct_class" in the "post-auth" section in order to
# create a Class attribute.
#
column_name = # ", Class"
packet_xlat = # ", '%{Class}'"
reply_xlat = # ", '%{reply:Class}'"
}
#######################################################################
# Default profile
#######################################################################
# This is the default profile. It is found in SQL by group membership.
# That means that this profile must be a member of at least one group
# which will contain the corresponding check and reply items.
# This profile will be queried in the authorize section for every user.
# The point is to assign all users a default profile without having to
# manually add each one to a group that will contain the profile.
# The SQL module will also honor the User-Profile attribute. This
# attribute can be set anywhere in the authorize section (ie the users
# file). It is found exactly as the default profile is found.
# If it is set then it will *overwrite* the default profile setting.
# The idea is to select profiles based on checks on the incoming
# packets, not on user group membership. For example:
# -- users file --
# DEFAULT Service-Type == Outbound-User, User-Profile := "outbound"
# DEFAULT Service-Type == Framed-User, User-Profile := "framed"
#
# By default the default_user_profile is not set
#
# default_user_profile = "DEFAULT"
#######################################################################
# Open Query
#######################################################################
# This query is run whenever a new connection is opened.
# It is commented out by default.
#
# If you have issues with connections hanging for too long, uncomment
# the next line, and set the timeout in milliseconds. As a general
# rule, if the queries take longer than a second, something is wrong
# with the database.
#open_query = "set statement_timeout to 1000"
#######################################################################
# NAS Query
#######################################################################
# This query retrieves the radius clients
#
# 0. Row ID (currently unused)
# 1. Name (or IP address)
# 2. Shortname
# 3. Type
# 4. Secret
# 5. Server
#######################################################################
client_query = "\
SELECT id, nasname, shortname, type, secret, server \
FROM ${client_table}"
#######################################################################
# Authorization Queries
#######################################################################
# These queries compare the check items for the user
# in ${authcheck_table} and setup the reply items in
# ${authreply_table}. You can use any query/tables
# you want, but the return data for each row MUST
# be in the following order:
#
# 0. Row ID (currently unused)
# 1. UserName/GroupName
# 2. Item Attr Name
# 3. Item Attr Value
# 4. Item Attr Operation
#######################################################################
#
# Use these for case insensitive usernames. WARNING: Slower queries!
#
#authorize_check_query = "\
# SELECT id, UserName, Attribute, Value, Op \
# FROM ${authcheck_table} \
# WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
# ORDER BY id"
#authorize_reply_query = "\
# SELECT id, UserName, Attribute, Value, Op \
# FROM ${authreply_table} \
# WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
# ORDER BY id"
authorize_check_query = "\
SELECT id, UserName, Attribute, Value, Op \
FROM ${authcheck_table} \
WHERE Username = '%{SQL-User-Name}' \
ORDER BY id"
authorize_reply_query = "\
SELECT id, UserName, Attribute, Value, Op \
FROM ${authreply_table} \
WHERE Username = '%{SQL-User-Name}' \
ORDER BY id"
#
# Use these for case insensitive usernames. WARNING: Slower queries!
#
#authorize_group_check_query = "\
# SELECT \
# ${groupcheck_table}.id, ${groupcheck_table}.GroupName, ${groupcheck_table}.Attribute, \
# ${groupcheck_table}.Value, ${groupcheck_table}.Op \
# FROM ${groupcheck_table}, ${usergroup_table} \
# WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') \
# AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
# ORDER BY ${groupcheck_table}.id"
#authorize_group_reply_query = "\
# SELECT \
# ${groupreply_table}.id, ${groupreply_table}.GroupName, \
# ${groupreply_table}.Attribute, ${groupreply_table}.Value, ${groupreply_table}.Op \
# FROM ${groupreply_table}, ${usergroup_table} \
# WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') \
# AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
# ORDER BY ${groupreply_table}.id"
authorize_group_check_query = "\
SELECT id, GroupName, Attribute, Value, op \
FROM ${groupcheck_table} \
WHERE GroupName = '%{${group_attribute}}' \
ORDER BY id"
authorize_group_reply_query = "\
SELECT id, GroupName, Attribute, Value, op \
FROM ${groupreply_table} \
WHERE GroupName = '%{${group_attribute}}' \
ORDER BY id"
#######################################################################
# Simultaneous Use Checking Queries
#######################################################################
# simul_count_query - query for the number of current connections
# - If this is not defined, no simultaneous use checking
# - will be performed by this module instance
# simul_verify_query - query to return details of current connections for verification
# - Leave blank or commented out to disable verification step
# - Note that the returned field order should not be changed.
#######################################################################
simul_count_query = "\
SELECT COUNT(RadAcctId) \
FROM ${acct_table1} a \
LEFT OUTER JOIN nasreload n USING (NASIPAddress) \
WHERE UserName='%{SQL-User-Name}' \
AND AcctStopTime IS NULL \
AND (a.AcctStartTime > n.ReloadTime OR n.ReloadTime IS NULL)"
simul_verify_query = "\
SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, \
FramedProtocol \
FROM ${acct_table1} a \
LEFT OUTER JOIN nasreload n USING (nasipaddress) \
WHERE UserName='%{SQL-User-Name}' \
AND AcctStopTime IS NULL \
AND (a.AcctStartTime > n.reloadtime OR n.reloadtime IS NULL)"
#######################################################################
# Group Membership Queries
#######################################################################
# group_membership_query - Check user group membership
#######################################################################
# Use these for case insensitive usernames. WARNING: Slower queries!
#group_membership_query = "\
# SELECT GroupName \
# FROM ${usergroup_table} \
# WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
# ORDER BY priority"
group_membership_query = "\
SELECT GroupName \
FROM ${usergroup_table} \
WHERE UserName='%{SQL-User-Name}' \
ORDER BY priority"
#######################################################################
# Accounting and Post-Auth Queries
#######################################################################
# These queries insert/update accounting and authentication records.
# The query to use is determined by the value of 'reference'.
# This value is used as a configuration path and should resolve to one
# or more 'query's. If reference points to multiple queries, and a query
# fails, the next query is executed.
#
# Behaviour is identical to the old 1.x/2.x module, except we can now
# fail between N queries, and query selection can be based on any
# combination of attributes, or custom 'Acct-Status-Type' values.
#######################################################################
accounting {
reference = "%{tolower:type.%{%{Acct-Status-Type}:-%{Request-Processing-Stage}}.query}"
# Write SQL queries to a logfile. This is potentially useful for bulk inserts
# when used with the rlm_sql_null driver.
# logfile = ${logdir}/accounting.sql
column_list = "\
AcctSessionId, \
AcctUniqueId, \
UserName, \
Realm, \
NASIPAddress, \
NASPortId, \
NASPortType, \
AcctStartTime, \
AcctUpdateTime, \
AcctStopTime, \
AcctSessionTime, \
AcctAuthentic, \
ConnectInfo_start, \
ConnectInfo_Stop, \
AcctInputOctets, \
AcctOutputOctets, \
CalledStationId, \
CallingStationId, \
AcctTerminateCause, \
ServiceType, \
FramedProtocol, \
FramedIpAddress, \
FramedIpv6Address, \
FramedIpv6Prefix, \
FramedInterfaceId, \
DelegatedIpv6Prefix \
${..class.column_name}"
type {
accounting-on {
#
# "Bulk update" Accounting-On/Off strategy.
#
# Immediately terminate all sessions associated with a
# given NAS.
#
# Note: If a large number of sessions require closing
# then the bulk update may be take a long time to run
# and lock an excessive number of rows. See the
# strategy below for an alternative approach that does
# not touch the radacct session data.
#
query = "\
UPDATE ${....acct_table1} \
SET \
AcctStopTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
AcctSessionTime = (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime))), \
AcctTerminateCause = '%{%{Acct-Terminate-Cause}:-NAS-Reboot}' \
WHERE AcctStopTime IS NULL \
AND NASIPAddress= '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \
AND AcctStartTime <= ${....event_timestamp}"
#
# "Lightweight" Accounting-On/Off strategy.
#
# Record the reload time of the NAS and let the
# administrator actually close the sessions in radacct
# out-of-band, if desired.
#
# Implementation advice, together with a stored
# procedure for closing sessions and a view showing
# the effective stop time of each session is provided
# in process-radacct.sql.
#
# To enable this strategy, just change the previous
# query to "-query", and this one to "query". The
# previous one will be ignored, and this one will be
# enabled.
#
-query = "\
INSERT INTO nasreload (NASIPAddress, ReloadTime) \
VALUES ('%{NAS-IP-Address}', ${....event_timestamp}) \
ON CONFLICT ON (NASIPAddress) \
DO UPDATE SET \
ReloadTime = ${....event_timestamp}"
}
accounting-off {
query = "${..accounting-on.query}"
}
#
# Implement the "sql_session_start" policy.
# See raddb/policy.d/accounting for more details.
#
# You also need to fix the other queries as
# documented below. Look for "sql_session_start".
#
post-auth {
query = "\
INSERT INTO ${....acct_table1} \
(${...column_list}) \
VALUES(\
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
NULLIF('%{Realm}', ''), \
'%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
'%{NAS-Port-Type}', \
${....event_timestamp}, \
${....event_timestamp}, \
NULL, \
0, \
'', \
'%{Connect-Info}', \
NULL, \
0, \
0, \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
NULL, \
'%{Service-Type}', \
'', \
NULL, \
NULL, \
NULL, \
NULL, \
NULL \
${....class.reply_xlat})"
query = "\
UPDATE ${....acct_table1} \
SET \
AcctStartTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
ConnectInfo_start = '%{Connect-Info}', \
AcctSessionId = '%{Acct-Session-Id}' \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND AcctStopTime IS NULL"
}
start {
query = "\
INSERT INTO ${....acct_table1} \
(${...column_list}) \
VALUES(\
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
NULLIF('%{Realm}', ''), \
'%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
'%{NAS-Port-Type}', \
${....event_timestamp}, \
${....event_timestamp}, \
NULL, \
0, \
'%{Acct-Authentic}', \
'%{Connect-Info}', \
NULL, \
0, \
0, \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
NULL, \
'%{Service-Type}', \
'%{Framed-Protocol}', \
NULLIF('%{Framed-IP-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
NULLIF('%{Framed-Interface-Id}', ''), \
NULLIF('%{Delegated-IPv6-Prefix}', '')::inet \
${....class.packet_xlat} ) \
ON CONFLICT (AcctUniqueId) \
DO UPDATE \
SET \
AcctStartTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
ConnectInfo_start = '%{Connect-Info}' \
WHERE ${....acct_table1}.AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND ${....acct_table1}.AcctStopTime IS NULL"
#
# When using "sql_session_start", you should comment out
# the previous query, and enable this one.
#
# Just change the previous query to "-query",
# and this one to "query". The previous one
# will be ignored, and this one will be
# enabled.
#
-query = "\
UPDATE ${....acct_table1} \
SET \
AcctSessionId = '%{Acct-Session-Id}', \
AcctUniqueId = '%{Acct-Unique-Session-Id}', \
AcctAuthentic = '%{Acct-Authentic}', \
ConnectInfo_start = '%{Connect-Info}', \
ServiceType = '%{Service-Type}', \
FramedProtocol = '%{Framed-Protocol}', \
FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \
FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \
DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \
AcctStartTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp} \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND AcctStopTime IS NULL"
# and again where we don't have "AND AcctStopTime IS NULL"
query = "\
UPDATE ${....acct_table1} \
SET \
AcctStartTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
ConnectInfo_start = '%{Connect-Info}' \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'"
}
interim-update {
query = "\
UPDATE ${....acct_table1} \
SET \
FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \
FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \
DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \
AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \
AcctInterval = (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM (COALESCE(AcctUpdateTime, AcctStartTime)))), \
AcctUpdateTime = ${....event_timestamp}, \
AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint) \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND AcctStopTime IS NULL"
query = "\
INSERT INTO ${....acct_table1} \
(${...column_list}) \
VALUES(\
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
NULLIF('%{Realm}', ''), \
'%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
'%{NAS-Port-Type}', \
TO_TIMESTAMP(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
${....event_timestamp}, \
NULL, \
%{%{Acct-Session-Time}:-NULL}, \
'%{Acct-Authentic}', \
'%{Connect-Info}', \
NULL, \
(('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
(('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint), \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
NULL, \
'%{Service-Type}', \
'%{Framed-Protocol}', \
NULLIF('%{Framed-IP-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
NULLIF('%{Framed-Interface-Id}', ''), \
NULLIF('%{Delegated-IPv6-Prefix}', '')::inet \
${....class.packet_xlat}) \
ON CONFLICT (AcctUniqueId) \
DO NOTHING"
#
# When using "sql_session_start", you should comment out
# the previous query, and enable this one.
#
# Just change the previous query to "-query",
# and this one to "query". The previous one
# will be ignored, and this one will be
# enabled.
#
-query = "\
UPDATE ${....acct_table1} \
SET \
AcctSessionId = '%{Acct-Session-Id}', \
AcctUniqueId = '%{Acct-Unique-Session-Id}', \
AcctAuthentic = '%{Acct-Authentic}', \
ConnectInfo_start = '%{Connect-Info}', \
ServiceType = '%{Service-Type}', \
FramedProtocol = '%{Framed-Protocol}', \
FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \
FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \
DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \
AcctUpdateTime = ${....event_timestamp}, \
AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \
(${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \
AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint) \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND AcctStopTime IS NULL"
}
stop {
query = "\
UPDATE ${....acct_table2} \
SET \
AcctStopTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \
(${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \
AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint), \
AcctTerminateCause = '%{Acct-Terminate-Cause}', \
FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \
FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \
DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \
ConnectInfo_stop = '%{Connect-Info}' \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND AcctStopTime IS NULL"
query = "\
INSERT INTO ${....acct_table1} \
(${...column_list}) \
VALUES(\
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
NULLIF('%{Realm}', ''), \
'%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
'%{NAS-Port-Type}', \
TO_TIMESTAMP(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
${....event_timestamp}, \
${....event_timestamp}, \
NULLIF('%{Acct-Session-Time}', '')::bigint, \
'%{Acct-Authentic}', \
'%{Connect-Info}', \
NULL, \
(('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
(('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint), \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Acct-Terminate-Cause}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
NULLIF('%{Framed-IP-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
NULLIF('%{Framed-Interface-Id}', ''), \
NULLIF('%{Delegated-IPv6-Prefix}', '')::inet \
${....class.packet_xlat}) \
ON CONFLICT (AcctUniqueId) \
DO NOTHING"
#
# When using "sql_session_start", you should comment out
# the previous query, and enable this one.
#
# Just change the previous query to "-query",
# and this one to "query". The previous one
# will be ignored, and this one will be
# enabled.
#
-query = "\
UPDATE ${....acct_table1} \
SET \
AcctSessionId = '%{Acct-Session-Id}', \
AcctUniqueId = '%{Acct-Unique-Session-Id}', \
AcctAuthentic = '%{Acct-Authentic}', \
ConnectInfo_start = '%{Connect-Info}', \
ServiceType = '%{Service-Type}', \
FramedProtocol = '%{Framed-Protocol}', \
FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \
FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \
DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \
AcctStopTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \
(${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \
AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint), \
AcctTerminateCause = '%{Acct-Terminate-Cause}', \
ConnectInfo_stop = '%{Connect-Info}' \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \
AND AcctStopTime IS NULL"
# and again where we don't have "AND AcctStopTime IS NULL"
query = "\
UPDATE ${....acct_table2} \
SET \
AcctStopTime = ${....event_timestamp}, \
AcctUpdateTime = ${....event_timestamp}, \
AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \
(${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \
AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint), \
AcctTerminateCause = '%{Acct-Terminate-Cause}', \
FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \
FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \
DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \
ConnectInfo_stop = '%{Connect-Info}' \
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'"
}
#
# No Acct-Status-Type == ignore the packet
#
accounting {
query = "SELECT true"
}
}
}
#######################################################################
# Authentication Logging Queries
#######################################################################
# postauth_query - Insert some info after authentication
#######################################################################
post-auth {
# Write SQL queries to a logfile. This is potentially useful for bulk inserts
# when used with the rlm_sql_null driver.
# logfile = ${logdir}/post-auth.sql
query = "\
INSERT INTO ${..postauth_table} \
(username, reply, authdate ${..class.column_name}) \
VALUES(\
'%{User-Name}', \
'%{reply:Packet-Type}', \
'%S.%M' \
${..class.reply_xlat})"
}
@@ -6,7 +6,7 @@ SPDX-License-Identifier: APACHE-2.0
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ printf "%s-mods-config" (include "st-common.names.fullname" .) }} name: {{ printf "%s-mods-config-mysql-queries" (include "st-common.names.fullname" .) }}
namespace: {{ include "st-common.names.namespace" . | quote }} namespace: {{ include "st-common.names.namespace" . | quote }}
labels: {{- include "st-common.labels.standard" . | nindent 4 }} labels: {{- include "st-common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }} {{- if .Values.commonLabels }}
@@ -16,4 +16,4 @@ metadata:
annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }}
{{- end }} {{- end }}
data: data:
{{ (.Files.Glob "files/mods-config/queries.conf").AsConfig | indent 2 }} {{ (.Files.Glob "files/mods-config/mysql-queries.conf").AsConfig | indent 2 }}
@@ -0,0 +1,19 @@
{{- /*
Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-mods-config-postgres-queries" (include "st-common.names.fullname" .) }}
namespace: {{ include "st-common.names.namespace" . | quote }}
labels: {{- include "st-common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }}
{{- end }}
data:
{{ (.Files.Glob "files/mods-config/postgres-queries.conf").AsConfig | indent 2 }}
+9 -3
View File
@@ -283,8 +283,11 @@ spec:
- name: freeradius-mods - name: freeradius-mods
mountPath: /etc/freeradius/mods-enabled/sqlippool mountPath: /etc/freeradius/mods-enabled/sqlippool
subPath: sqlippool subPath: sqlippool
- name: freeradius-mods-config - name: freeradius-mods-config-mysql-queries
mountPath: /etc/freeradius/mods-config/sql/main/mysql/queries.conf mountPath: /etc/freeradius/mods-config/sql/main/mysql/queries.conf
subPath: queries.conf
- name: freeradius-mods-config-postgres-queries
mountPath: /etc/freeradius/mods-config/sql/main/postgresql/queries.conf
subPath: queries.conf subPath: queries.conf
- name: freeradius-radius-conf - name: freeradius-radius-conf
mountPath: /etc/freeradius/radius.conf mountPath: /etc/freeradius/radius.conf
@@ -340,9 +343,12 @@ spec:
- name: freeradius-sites - name: freeradius-sites
configMap: configMap:
name: {{ printf "%s-sites" (include "st-common.names.fullname" .) }} name: {{ printf "%s-sites" (include "st-common.names.fullname" .) }}
- name: freeradius-mods-config - name: freeradius-mods-config-mysql-queries
configMap: configMap:
name: {{ printf "%s-mods-config" (include "st-common.names.fullname" .) }} name: {{ printf "%s-mods-config-mysql-queries" (include "st-common.names.fullname" .) }}
- name: freeradius-mods-config-postgres-queries
configMap:
name: {{ printf "%s-mods-config-postgres-queries" (include "st-common.names.fullname" .) }}
- name: freeradius-radius-conf - name: freeradius-radius-conf
configMap: configMap:
name: {{ printf "%s-radius-conf" (include "st-common.names.fullname" .) }} name: {{ printf "%s-radius-conf" (include "st-common.names.fullname" .) }}