Compare commits
29
Commits
1.0.3
..
cf98b8dd81
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf98b8dd81 | ||
|
|
8217c2ee61 | ||
|
|
4f9937d351 | ||
|
|
a656e83473 | ||
|
|
20b260a795 | ||
|
|
eeeb230b2b | ||
|
|
41834f6ab4 | ||
|
|
1a1e37ffdf | ||
|
|
328ff7511c | ||
|
|
064bda9e20 | ||
|
|
69a4e3a3b8 | ||
|
|
fca66dfa52 | ||
|
|
8c1289f92e | ||
|
|
c245ab29af | ||
|
|
629a51a905 | ||
|
|
fc35d35b00 | ||
|
|
35e0f2f419 | ||
|
|
7d90707deb | ||
|
|
e50df4ba36 | ||
|
|
a08dcf6983 | ||
|
|
aad17e7b3f | ||
|
|
4885bc1eb4 | ||
|
|
3ccf50ed57 | ||
|
|
f025437c6a | ||
|
|
bb0a10b2bf | ||
|
|
a7e7202761 | ||
|
|
763d743c16 | ||
|
|
642f747b48 | ||
|
|
98c2fa6240 |
@@ -0,0 +1 @@
|
||||
charts/
|
||||
+23
-2
@@ -8,9 +8,13 @@ stages:
|
||||
|
||||
variables:
|
||||
CHART_NAME: "freeradius"
|
||||
CHART_VERSION: "1.0.3"
|
||||
CHART_VERSION: "2.0.0"
|
||||
PACKAGE_PATH: "packages"
|
||||
ST_COMMON_PROJECT_ID: "270"
|
||||
COMMON_PROJECT_URL: "${CI_API_V4_URL}/projects/${ST_COMMON_PROJECT_ID}/packages/helm/stable"
|
||||
HELM_EXPERIMENTAL_OCI: "1"
|
||||
GITEA_URL: "gitea.infrastructure.helmholz.cloud"
|
||||
GITEA_REPO: "oci://gitea.infrastructure.helmholz.cloud/gitea_admin/helm"
|
||||
|
||||
package_chart:
|
||||
stage: package
|
||||
@@ -18,7 +22,7 @@ package_chart:
|
||||
name: alpine/helm:3.14.0
|
||||
entrypoint: [""]
|
||||
script:
|
||||
- helm repo add startechnica https://startechnica.github.io/apps
|
||||
- helm repo add st-common ${COMMON_PROJECT_URL} --username gitlab-ci-token --password $CI_JOB_TOKEN
|
||||
- helm dependency build .
|
||||
- mkdir -p $PACKAGE_PATH
|
||||
- helm package . --destination $PACKAGE_PATH
|
||||
@@ -38,3 +42,20 @@ publish_chart:
|
||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/stable/charts"
|
||||
only:
|
||||
- main
|
||||
|
||||
push_chart_to_gitea:
|
||||
stage: publish
|
||||
image:
|
||||
name: alpine/helm:3.14.0
|
||||
entrypoint: [""]
|
||||
variables:
|
||||
GITEA_URL: "https://gitea.infrastructure.helmholz.cloud"
|
||||
GITEA_USERNAME: "gitea_admin"
|
||||
GITEA_PASSWORD: "$GITEA_PASSWORD"
|
||||
script:
|
||||
- echo "$GITEA_PASSWORD" | helm registry login $GITEA_URL --username $GITEA_USERNAME --password-stdin
|
||||
- helm push ${PACKAGE_PATH}/${CHART_NAME}-${CHART_VERSION}.tgz $GITEA_REPO
|
||||
only:
|
||||
- main
|
||||
dependencies:
|
||||
- package_chart
|
||||
@@ -0,0 +1 @@
|
||||
.git/
|
||||
+3
-6
@@ -1,9 +1,6 @@
|
||||
dependencies:
|
||||
- name: st-common
|
||||
repository: https://startechnica.github.io/apps
|
||||
repository: oci://gitea.infrastructure.helmholz.cloud/gitea_admin/helm
|
||||
version: 0.1.12
|
||||
- name: mariadb
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
version: 20.5.9
|
||||
digest: sha256:03a311ace58596d28267595eab6c85c5d39af13a5864dbe04be8931a2262b6c7
|
||||
generated: "2025-06-16T16:20:04.252816273+02:00"
|
||||
digest: sha256:9087809c86edc369e5d169ea3fd4dbded039b243b50af7b9df18c4b6f168257f
|
||||
generated: "2026-07-31T10:36:14.679991115+02:00"
|
||||
|
||||
+2
-6
@@ -4,12 +4,8 @@ apiVersion: v2
|
||||
appVersion: 3.2.7
|
||||
dependencies:
|
||||
- name: st-common
|
||||
repository: https://startechnica.github.io/apps
|
||||
repository: oci://gitea.infrastructure.helmholz.cloud/gitea_admin/helm
|
||||
version: 0.1.12
|
||||
- condition: mariadb.enabled
|
||||
name: mariadb
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
version: 20.x.x
|
||||
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
|
||||
download and use.
|
||||
@@ -31,4 +27,4 @@ sources:
|
||||
- https://freeradius.org/
|
||||
- https://github.com/FreeRADIUS/freeradius-server
|
||||
type: application
|
||||
version: 1.0.3
|
||||
version: 2.0.0
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ server radsec {
|
||||
|
||||
# Require a client certificate.
|
||||
#
|
||||
require_client_cert = yes
|
||||
require_client_cert = no
|
||||
|
||||
#
|
||||
# As of version 2.1.10, client certificates can be validated via an external command. This allows dynamic CRLs or OCSP to be used.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,41 @@
|
||||
# -*- text -*-
|
||||
#
|
||||
# $Id: cc2bd5fd22aa473b98af5dde3fac7a66e39a9e9d $
|
||||
|
||||
# This module loads RADIUS clients as needed, rather than when the server
|
||||
# starts.
|
||||
#
|
||||
# There are no configuration entries for this module. Instead, it
|
||||
# relies on the "client" configuration. You must:
|
||||
#
|
||||
# 1) link raddb/sites-enabled/dynamic_clients to
|
||||
# raddb/sites-available/dynamic_clients
|
||||
#
|
||||
# 2) Define a client network/mask (see top of the above file)
|
||||
#
|
||||
# 3) uncomment the "directory" entry in that client definition
|
||||
#
|
||||
# 4) list "dynamic_clients" in the "authorize" section of the
|
||||
# "dynamic_clients' virtual server. The default example already
|
||||
# does this.
|
||||
#
|
||||
# 5) put files into the above directory, one per IP.
|
||||
# e.g. file "192.0.2.1" should contain a normal client definition
|
||||
# for a client with IP address 192.0.2.1.
|
||||
#
|
||||
# For more documentation, see the file:
|
||||
#
|
||||
# raddb/sites-available/dynamic-clients
|
||||
#
|
||||
dynamic_clients {
|
||||
sql = "SELECT secret, shortname, type FROM nas WHERE nasname = '%{Packet-Src-IP-Address}'"
|
||||
|
||||
key = "%{Packet-Src-IP-Address}"
|
||||
|
||||
client {
|
||||
ipaddr = "%{Packet-Src-IP-Address}"
|
||||
secret = "%{reply:secret}"
|
||||
shortname = "%{reply:shortname}"
|
||||
nastype = "%{reply:type}"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,110 @@
|
||||
# Configuration for the SQL based IP Pool module (rlm_sqlippool)
|
||||
#
|
||||
# The database schemas are available at:
|
||||
#
|
||||
# raddb/mods-config/sql/ippool/<DB>/schema.sql
|
||||
#
|
||||
# $Id: f17a9898e906d3db0ad5871d8683f731f7a6baab $
|
||||
|
||||
sqlippool {
|
||||
# SQL instance to use (from mods-available/sql)
|
||||
#
|
||||
# If you have multiple sql instances, such as "sql sql1 {...}",
|
||||
# use the *instance* name here: sql1.
|
||||
sql_module_instance = "sql"
|
||||
|
||||
# This is duplicative of info available in the SQL module, but
|
||||
# we have to list it here as we do not yet support nested
|
||||
# reference expansions.
|
||||
dialect = $ENV{FREERADIUS_MODS_SQL_DIALECT}
|
||||
|
||||
# Name of the check item attribute to be used as a key in the SQL queries
|
||||
pool_name = "Pool-Name"
|
||||
|
||||
# SQL table to use for ippool range and lease info
|
||||
ippool_table = $ENV{FREERADIUS_MODS_SQL_TABLE_RADIPPOOL}
|
||||
|
||||
# IP lease duration. (Leases expire even if Acct Stop packet is lost)
|
||||
#
|
||||
# Note that you SHOULD also set Session-Timeout to this value!
|
||||
# That way the NAS will automatically kick the user offline when the
|
||||
# lease expires.
|
||||
#
|
||||
lease_duration = 18000
|
||||
|
||||
#
|
||||
# Timeout between each consecutive 'allocate_clear' queries (default: 1s)
|
||||
# This will avoid having too many deadlock issues, especially on MySQL backend.
|
||||
#
|
||||
allocate_clear_timeout = 1
|
||||
|
||||
#
|
||||
# The attribute to use for IP address assignment. The
|
||||
# default is Framed-IP-Address. You can change this to any
|
||||
# attribute which is IPv4 or IPv6.
|
||||
#
|
||||
# e.g. Framed-IPv6-Prefix, or Delegated-IPv6-Prefix.
|
||||
#
|
||||
# All of the default queries use this attribute_name. So you
|
||||
# can do IPv6 address assignment simply by putting IPv6
|
||||
# addresses into the pool, and changing the following line to
|
||||
# "Framed-IPv6-Prefix"
|
||||
#
|
||||
# Note that you MUST use separate pools for each attribute. i.e. one pool
|
||||
# for Framed-IP-Address, a different one for Framed-IPv6-prefix, etc.
|
||||
#
|
||||
# This means configuring separate "sqlippool" instances, and different
|
||||
# "ippool_table" in SQL. Then, populate the pool with addresses and
|
||||
# it will all just work.
|
||||
#
|
||||
attribute_name = Framed-IP-Address
|
||||
|
||||
#
|
||||
# Assign the IP address, even if the above attribute already exists
|
||||
# in the reply.
|
||||
#
|
||||
# allow_duplicates = no
|
||||
|
||||
# The attribute in which an IP address hint may be supplied
|
||||
req_attribute_name = Framed-IP-Address
|
||||
|
||||
# Attribute which should be considered unique per NAS
|
||||
#
|
||||
# Using NAS-Port gives behaviour similar to rlm_ippool. (And ACS)
|
||||
# Using Calling-Station-Id works for NAS that send fixed NAS-Port
|
||||
# ONLY change this if you know what you are doing!
|
||||
# pool_key = "%{NAS-Port}"
|
||||
# pool_key = "%{Calling-Station-Id}"
|
||||
pool_key = "%{User-Name}"
|
||||
nas_ip_address = "%{NAS-IP-Address}"
|
||||
################################################################
|
||||
#
|
||||
# WARNING: MySQL (MyISAM) has certain limitations that means it can
|
||||
# hand out the same IP address to 2 different users.
|
||||
#
|
||||
# We suggest using an SQL DB with proper transaction
|
||||
# support, such as PostgreSQL, or using MySQL
|
||||
# with InnoDB.
|
||||
#
|
||||
################################################################
|
||||
|
||||
# These messages are added to the "control" items, as
|
||||
# Module-Success-Message. They are not logged anywhere else,
|
||||
# unlike previous versions. If you want to have them logged
|
||||
# to a file, see the "linelog" module, and create an entry
|
||||
# which writes Module-Success-Message message.
|
||||
#
|
||||
messages {
|
||||
exists = "Existing IP: %{reply:${..attribute_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
|
||||
|
||||
success = "Allocated IP: %{reply:${..attribute_name}} from %{control:${..pool_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
|
||||
|
||||
clear = "Released IP %{request:${..attribute_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})"
|
||||
|
||||
failed = "IP Allocation FAILED from %{control:${..pool_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
|
||||
|
||||
nopool = "No ${..pool_name} defined (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
|
||||
}
|
||||
|
||||
$INCLUDE ${modconfdir}/sql/ippool/${dialect}/queries.conf
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
# -*- text -*-
|
||||
#
|
||||
# main/mysql/queries.conf-- MySQL configuration for default schema (schema.sql)
|
||||
#
|
||||
# $Id: b31ae9c3a1bf41f030a2112d31bf3a678e76f23c $
|
||||
|
||||
# Use the driver specific SQL escape method.
|
||||
#
|
||||
# If you enable this configuration item, the "safe_characters"
|
||||
# configuration is ignored. FreeRADIUS then uses the MySQL escape
|
||||
# functions to escape input strings. The only downside to making this
|
||||
# change is that the MySQL 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.-_: /"
|
||||
|
||||
#######################################################################
|
||||
# Connection config
|
||||
#######################################################################
|
||||
# The character set is not configurable. The default character set of
|
||||
# the mysql client library is used. To control the character set,
|
||||
# create/edit my.cnf (typically in /etc/mysql/my.cnf or /etc/my.cnf)
|
||||
# and enter
|
||||
# [freeradius]
|
||||
# default-character-set = utf8
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# 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 "DEFAULT" as the user name.
|
||||
#sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}"
|
||||
#
|
||||
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 = "FROM_UNIXTIME(${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"
|
||||
|
||||
#######################################################################
|
||||
# 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 sensitive usernames.
|
||||
|
||||
#authorize_check_query = "\
|
||||
# SELECT id, username, attribute, value, op \
|
||||
# FROM ${authcheck_table} \
|
||||
# WHERE username = BINARY '%{SQL-User-Name}' \
|
||||
# ORDER BY id"
|
||||
|
||||
#authorize_reply_query = "\
|
||||
# SELECT id, username, attribute, value, op \
|
||||
# FROM ${authreply_table} \
|
||||
# WHERE username = BINARY '%{SQL-User-Name}' \
|
||||
# ORDER BY id"
|
||||
|
||||
#
|
||||
# The default queries are case insensitive. (for compatibility with
|
||||
# older versions of FreeRADIUS)
|
||||
#
|
||||
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 sensitive usernames.
|
||||
#
|
||||
#group_membership_query = "\
|
||||
# SELECT groupname \
|
||||
# FROM ${usergroup_table} \
|
||||
# WHERE username = BINARY '%{SQL-User-Name}' \
|
||||
# ORDER BY priority"
|
||||
|
||||
group_membership_query = "\
|
||||
SELECT groupname \
|
||||
FROM ${usergroup_table} \
|
||||
WHERE username = '%{SQL-User-Name}' \
|
||||
ORDER BY priority"
|
||||
|
||||
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.
|
||||
#
|
||||
# Note: Sessions that started prior to the most recent reload of their NAS will
|
||||
# be correctly considered inactive, even if the radacct entry itself is not
|
||||
# marked as stopped.
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
simul_count_query = "\
|
||||
SELECT COUNT(*) \
|
||||
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)"
|
||||
|
||||
#######################################################################
|
||||
# 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}, \
|
||||
acctsessiontime = '${....event_timestamp_epoch}' \
|
||||
- UNIX_TIMESTAMP(acctstarttime), \
|
||||
acctterminatecause = '%{%{Acct-Terminate-Cause}:-NAS-Reboot}' \
|
||||
WHERE acctstoptime IS NULL \
|
||||
AND nasipaddress = '%{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 \
|
||||
SET \
|
||||
nasipaddress = '%{NAS-IP-Address}', \
|
||||
reloadtime = ${....event_timestamp} \
|
||||
ON DUPLICATE KEY UPDATE 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}', \
|
||||
'%{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}', \
|
||||
'', \
|
||||
'%{Service-Type}', \
|
||||
NULL, \
|
||||
'', \
|
||||
'', \
|
||||
'', \
|
||||
'', \
|
||||
'' \
|
||||
${....class.packet_xlat})"
|
||||
|
||||
query = "\
|
||||
UPDATE ${....acct_table1} SET \
|
||||
AcctStartTime = ${....event_timestamp}, \
|
||||
AcctUpdateTime = ${....event_timestamp}, \
|
||||
ConnectInfo_start = '%{Connect-Info}', \
|
||||
AcctSessionId = '%{Acct-Session-Id}' \
|
||||
WHERE UserName = '%{SQL-User-Name}' \
|
||||
AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \
|
||||
AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \
|
||||
AND NASPortType = '%{NAS-Port-Type}' \
|
||||
AND AcctStopTime IS NULL"
|
||||
}
|
||||
|
||||
start {
|
||||
#
|
||||
# Insert a new record into the sessions table
|
||||
#
|
||||
query = "\
|
||||
INSERT INTO ${....acct_table1} \
|
||||
(${...column_list}) \
|
||||
VALUES \
|
||||
('%{Acct-Session-Id}', \
|
||||
'%{Acct-Unique-Session-Id}', \
|
||||
'%{SQL-User-Name}', \
|
||||
'%{Realm}', \
|
||||
'%{NAS-IP-Address}', \
|
||||
'%{%{NAS-Port-ID}:-%{NAS-Port}}', \
|
||||
'%{NAS-Port-Type}', \
|
||||
${....event_timestamp}, \
|
||||
${....event_timestamp}, \
|
||||
NULL, \
|
||||
'0', \
|
||||
'%{Acct-Authentic}', \
|
||||
'%{Connect-Info}', \
|
||||
'', \
|
||||
'0', \
|
||||
'0', \
|
||||
'%{Called-Station-Id}', \
|
||||
'%{Calling-Station-Id}', \
|
||||
'', \
|
||||
'%{Service-Type}', \
|
||||
'%{Framed-Protocol}', \
|
||||
'%{Framed-IP-Address}', \
|
||||
'%{Framed-IPv6-Address}', \
|
||||
'%{Framed-IPv6-Prefix}', \
|
||||
'%{Framed-Interface-Id}', \
|
||||
'%{Delegated-IPv6-Prefix}' \
|
||||
${....class.packet_xlat})"
|
||||
|
||||
#
|
||||
# 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 = '%{Framed-IP-Address}', \
|
||||
framedipv6address = '%{Framed-IPv6-Address}', \
|
||||
framedipv6prefix = '%{Framed-IPv6-Prefix}', \
|
||||
framedinterfaceid = '%{Framed-Interface-Id}', \
|
||||
delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \
|
||||
AcctStartTime = ${....event_timestamp}, \
|
||||
AcctUpdateTime = ${....event_timestamp} \
|
||||
WHERE UserName = '%{SQL-User-Name}' \
|
||||
AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \
|
||||
AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \
|
||||
AND NASPortType = '%{NAS-Port-Type}' \
|
||||
AND AcctStopTime IS NULL"
|
||||
|
||||
#
|
||||
# Key constraints prevented us from inserting a new session,
|
||||
# use the alternate query to update an existing session.
|
||||
#
|
||||
query = "\
|
||||
UPDATE ${....acct_table1} SET \
|
||||
acctstarttime = ${....event_timestamp}, \
|
||||
acctupdatetime = ${....event_timestamp}, \
|
||||
connectinfo_start = '%{Connect-Info}' \
|
||||
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'"
|
||||
|
||||
}
|
||||
|
||||
interim-update {
|
||||
#
|
||||
# Update an existing session and calculate the interval
|
||||
# between the last data we received for the session and this
|
||||
# update. This can be used to find stale sessions.
|
||||
#
|
||||
query = "\
|
||||
UPDATE ${....acct_table1} \
|
||||
SET \
|
||||
acctupdatetime = (@acctupdatetime_old:=acctupdatetime), \
|
||||
acctupdatetime = ${....event_timestamp}, \
|
||||
acctinterval = ${....event_timestamp_epoch} - \
|
||||
UNIX_TIMESTAMP(@acctupdatetime_old), \
|
||||
framedipaddress = '%{Framed-IP-Address}', \
|
||||
framedipv6address = '%{Framed-IPv6-Address}', \
|
||||
framedipv6prefix = '%{Framed-IPv6-Prefix}', \
|
||||
framedinterfaceid = '%{Framed-Interface-Id}', \
|
||||
delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \
|
||||
acctsessiontime = %{%{Acct-Session-Time}:-NULL}, \
|
||||
acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Input-Octets}:-0}', \
|
||||
acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Output-Octets}:-0}' \
|
||||
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'"
|
||||
|
||||
#
|
||||
# The update condition matched no existing sessions. Use
|
||||
# the values provided in the update to create a new session.
|
||||
#
|
||||
query = "\
|
||||
INSERT INTO ${....acct_table1} \
|
||||
(${...column_list}) \
|
||||
VALUES \
|
||||
('%{Acct-Session-Id}', \
|
||||
'%{Acct-Unique-Session-Id}', \
|
||||
'%{SQL-User-Name}', \
|
||||
'%{Realm}', \
|
||||
'%{NAS-IP-Address}', \
|
||||
'%{%{NAS-Port-ID}:-%{NAS-Port}}', \
|
||||
'%{NAS-Port-Type}', \
|
||||
FROM_UNIXTIME(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
|
||||
${....event_timestamp}, \
|
||||
NULL, \
|
||||
%{%{Acct-Session-Time}:-NULL}, \
|
||||
'%{Acct-Authentic}', \
|
||||
'%{Connect-Info}', \
|
||||
'', \
|
||||
'%{%{Acct-Input-Gigawords}:-0}' << 32 | '%{%{Acct-Input-Octets}:-0}', \
|
||||
'%{%{Acct-Output-Gigawords}:-0}' << 32 | '%{%{Acct-Output-Octets}:-0}', \
|
||||
'%{Called-Station-Id}', \
|
||||
'%{Calling-Station-Id}', \
|
||||
'', \
|
||||
'%{Service-Type}', \
|
||||
'%{Framed-Protocol}', \
|
||||
'%{Framed-IP-Address}', \
|
||||
'%{Framed-IPv6-Address}', \
|
||||
'%{Framed-IPv6-Prefix}', \
|
||||
'%{Framed-Interface-Id}', \
|
||||
'%{Delegated-IPv6-Prefix}' \
|
||||
${....class.packet_xlat})"
|
||||
|
||||
#
|
||||
# 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 = '%{Framed-IP-Address}', \
|
||||
framedipv6address = '%{Framed-IPv6-Address}', \
|
||||
framedipv6prefix = '%{Framed-IPv6-Prefix}', \
|
||||
framedinterfaceid = '%{Framed-Interface-Id}', \
|
||||
delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \
|
||||
AcctUpdateTime = ${....event_timestamp}, \
|
||||
AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \
|
||||
AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Input-Octets}:-0}', \
|
||||
AcctOutputOctets = '%{%{Acct-Output-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Output-Octets}:-0}' \
|
||||
WHERE UserName = '%{SQL-User-Name}' \
|
||||
AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \
|
||||
AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \
|
||||
AND NASPortType = '%{NAS-Port-Type}' \
|
||||
AND AcctStopTime IS NULL"
|
||||
|
||||
}
|
||||
|
||||
stop {
|
||||
#
|
||||
# Session has terminated, update the stop time and statistics.
|
||||
#
|
||||
query = "\
|
||||
UPDATE ${....acct_table2} SET \
|
||||
acctstoptime = ${....event_timestamp}, \
|
||||
acctsessiontime = %{%{Acct-Session-Time}:-NULL}, \
|
||||
acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Input-Octets}:-0}', \
|
||||
acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Output-Octets}:-0}', \
|
||||
acctterminatecause = '%{Acct-Terminate-Cause}', \
|
||||
connectinfo_stop = '%{Connect-Info}' \
|
||||
WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'"
|
||||
|
||||
#
|
||||
# The update condition matched no existing sessions. Use
|
||||
# the values provided in the update to create a new session.
|
||||
#
|
||||
query = "\
|
||||
INSERT INTO ${....acct_table2} \
|
||||
(${...column_list}) \
|
||||
VALUES \
|
||||
('%{Acct-Session-Id}', \
|
||||
'%{Acct-Unique-Session-Id}', \
|
||||
'%{SQL-User-Name}', \
|
||||
'%{Realm}', \
|
||||
'%{NAS-IP-Address}', \
|
||||
'%{%{NAS-Port-ID}:-%{NAS-Port}}', \
|
||||
'%{NAS-Port-Type}', \
|
||||
FROM_UNIXTIME(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
|
||||
${....event_timestamp}, \
|
||||
${....event_timestamp}, \
|
||||
%{%{Acct-Session-Time}:-NULL}, \
|
||||
'%{Acct-Authentic}', \
|
||||
'', \
|
||||
'%{Connect-Info}', \
|
||||
'%{%{Acct-Input-Gigawords}:-0}' << 32 | '%{%{Acct-Input-Octets}:-0}', \
|
||||
'%{%{Acct-Output-Gigawords}:-0}' << 32 | '%{%{Acct-Output-Octets}:-0}', \
|
||||
'%{Called-Station-Id}', \
|
||||
'%{Calling-Station-Id}', \
|
||||
'%{Acct-Terminate-Cause}', \
|
||||
'%{Service-Type}', \
|
||||
'%{Framed-Protocol}', \
|
||||
'%{Framed-IP-Address}', \
|
||||
'%{Framed-IPv6-Address}', \
|
||||
'%{Framed-IPv6-Prefix}', \
|
||||
'%{Framed-Interface-Id}', \
|
||||
'%{Delegated-IPv6-Prefix}' \
|
||||
${....class.packet_xlat})"
|
||||
|
||||
#
|
||||
# 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 = '%{Framed-IP-Address}', \
|
||||
framedipv6address = '%{Framed-IPv6-Address}', \
|
||||
framedipv6prefix = '%{Framed-IPv6-Prefix}', \
|
||||
framedinterfaceid = '%{Framed-Interface-Id}', \
|
||||
delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \
|
||||
AcctStopTime = ${....event_timestamp}, \
|
||||
AcctUpdateTime = ${....event_timestamp}, \
|
||||
AcctSessionTime = %{Acct-Session-Time}, \
|
||||
AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Input-Octets}:-0}', \
|
||||
AcctOutputOctets = '%{%{Acct-Output-Gigawords}:-0}' \
|
||||
<< 32 | '%{%{Acct-Output-Octets}:-0}', \
|
||||
AcctTerminateCause = '%{Acct-Terminate-Cause}', \
|
||||
ConnectInfo_stop = '%{Connect-Info}' \
|
||||
WHERE UserName = '%{SQL-User-Name}' \
|
||||
AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \
|
||||
AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \
|
||||
AND NASPortType = '%{NAS-Port-Type}' \
|
||||
AND AcctStopTime IS NULL"
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# 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, reason, authdate ${..class.column_name}) \
|
||||
VALUES ( \
|
||||
'%{SQL-User-Name}', \
|
||||
'%{reply:Packet-Type}', \
|
||||
'%{reply:Reply-Message}', \
|
||||
'%S.%M' \
|
||||
${..class.reply_xlat})"
|
||||
}
|
||||
@@ -0,0 +1,742 @@
|
||||
# -*- 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, reason, authdate ${..class.column_name}) \
|
||||
VALUES(\
|
||||
'%{User-Name}', \
|
||||
'%{reply:Packet-Type}', \
|
||||
'%{reply:Reply-Message}', \
|
||||
'%S.%M' \
|
||||
${..class.reply_xlat})"
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
#
|
||||
# Example of forbidding all attempts to login via
|
||||
# realms.
|
||||
#
|
||||
deny_realms {
|
||||
if (&User-Name && (&User-Name =~ /@|\\/)) {
|
||||
reject
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Filter the username
|
||||
#
|
||||
# Force some sanity on User-Name. This helps to avoid issues
|
||||
# issues where the back-end database is "forgiving" about
|
||||
# what constitutes a user name.
|
||||
#
|
||||
filter_username {
|
||||
if (&User-Name) {
|
||||
#
|
||||
# reject mixed case e.g. "UseRNaMe"
|
||||
#
|
||||
#if (&User-Name != "%{tolower:%{User-Name}}") {
|
||||
# reject
|
||||
#}
|
||||
|
||||
#
|
||||
# reject all whitespace
|
||||
# e.g. "user@ site.com", or "us er", or " user", or "user "
|
||||
#
|
||||
if (&User-Name =~ / /) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: User-Name contains whitespace'
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# reject Multiple @'s
|
||||
# e.g. "user@site.com@site.com"
|
||||
#
|
||||
if (&User-Name =~ /@[^@]*@/ ) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Multiple @ in User-Name'
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# reject double dots
|
||||
# e.g. "user@site..com"
|
||||
#
|
||||
if (&User-Name =~ /\.\./ ) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: User-Name contains multiple ..s'
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# must have at least 1 string-dot-string after @
|
||||
# e.g. "user@site.com"
|
||||
#
|
||||
# if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) {
|
||||
# update request {
|
||||
# &Module-Failure-Message += 'Rejected: Realm does not have at least one dot separator'
|
||||
# }
|
||||
# reject
|
||||
# }
|
||||
|
||||
#
|
||||
# Realm ends with a dot
|
||||
# e.g. "user@site.com."
|
||||
#
|
||||
if (&User-Name =~ /\.$/) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Realm ends with a dot'
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# Realm begins with a dot
|
||||
# e.g. "user@.site.com"
|
||||
#
|
||||
if (&User-Name =~ /@\./) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Realm begins with a dot'
|
||||
}
|
||||
reject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Filter the User-Password
|
||||
#
|
||||
# Some equipment sends passwords with embedded zeros.
|
||||
# This policy filters them out.
|
||||
#
|
||||
filter_password {
|
||||
if (&User-Password && \
|
||||
(&User-Password != "%{string:User-Password}")) {
|
||||
update request {
|
||||
&Tmp-String-0 := "%{string:User-Password}"
|
||||
&User-Password := "%{string:Tmp-String-0}"
|
||||
&Tmp-String-0 !* ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filter_inner_identity {
|
||||
#
|
||||
# No names, reject.
|
||||
#
|
||||
if (!&outer.request:User-Name || !&User-Name) {
|
||||
update request {
|
||||
Module-Failure-Message = "User-Name is required for tunneled authentication"
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# Do detailed checks only if the inner and outer
|
||||
# NAIs are different.
|
||||
#
|
||||
# If the NAIs are the same, it violates user privacy,
|
||||
# but is allowed.
|
||||
#
|
||||
if (&outer.request:User-Name != &User-Name) {
|
||||
#
|
||||
# Get the outer realm.
|
||||
#
|
||||
if (&outer.request:User-Name =~ /@([^@]+)$/) {
|
||||
update request {
|
||||
Outer-Realm-Name = "%{1}"
|
||||
}
|
||||
|
||||
#
|
||||
# When we have an outer realm name, the user portion
|
||||
# MUST either be empty, or begin with "anon".
|
||||
#
|
||||
# We don't check for the full "anonymous", because
|
||||
# some vendors don't follow the standards.
|
||||
#
|
||||
if (&outer.request:User-Name !~ /^(anon|@)/) {
|
||||
update request {
|
||||
Module-Failure-Message = "User-Name is not anonymized"
|
||||
}
|
||||
reject
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# There's no outer realm. The outer NAI is different from the
|
||||
# inner NAI. The User-Name MUST be anonymized.
|
||||
#
|
||||
# Otherwise, you could log in as outer "bob", and inner "doug",
|
||||
# and we'd have no idea which one was correct.
|
||||
#
|
||||
elsif (&outer.request:User-Name !~ /^anon/) {
|
||||
update request {
|
||||
Module-Failure-Message = "User-Name is not anonymized"
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# Get the inner realm.
|
||||
#
|
||||
if (&User-Name =~ /@([^@]+)$/) {
|
||||
update request {
|
||||
Inner-Realm-Name = "%{1}"
|
||||
}
|
||||
|
||||
#
|
||||
# Note that we do EQUALITY checks for realm names.
|
||||
# There is no simple way to do case insensitive checks
|
||||
# on internationalized domain names. There is no reason
|
||||
# to allow outer "anonymous@EXAMPLE.COM" and inner
|
||||
# "user@example.com". The user should enter the same
|
||||
# realm for both identities.
|
||||
#
|
||||
# If the inner realm isn't the same as the outer realm,
|
||||
# the inner realm MUST be a subdomain of the outer realm.
|
||||
#
|
||||
if (&Outer-Realm-Name && \
|
||||
(&Inner-Realm-Name != &Outer-Realm-Name) && \
|
||||
(&Inner-Realm-Name !~ /\.%{Outer-Realm-Name}$/)) {
|
||||
update request {
|
||||
Module-Failure-Message = "Inner realm '%{Inner-Realm-Name}' and outer realm '%{Outer-Realm-Name}' are not from the same domain."
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
#
|
||||
# It's OK to have an inner realm and no outer realm.
|
||||
#
|
||||
# That won't work for roaming, but the local RADIUS server
|
||||
# can still authenticate the user.
|
||||
#
|
||||
}
|
||||
|
||||
#
|
||||
# It's OK to have an outer realm and no inner realm.
|
||||
#
|
||||
# It will work for roaming, and the local RADIUS server
|
||||
# can authenticate the user without the realm.
|
||||
#
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
vlan_test {
|
||||
|
||||
if (&User-Name =~ /.+@(.+)/) {
|
||||
|
||||
update control {
|
||||
Tmp-String-0 := "%{1}"
|
||||
}
|
||||
|
||||
update reply {
|
||||
Tunnel-Type := VLAN
|
||||
Tunnel-Medium-Type := IEEE-802
|
||||
Tunnel-Private-Group-Id := "%{sql:SELECT vlan_id FROM tenant_subnets WHERE tenant_id='%{control:Tmp-String-0}'}"
|
||||
}
|
||||
}
|
||||
}
|
||||
+1143
File diff suppressed because it is too large
Load Diff
@@ -163,3 +163,22 @@ CREATE TABLE IF NOT EXISTS nas (
|
||||
PRIMARY KEY (id),
|
||||
KEY nasname (nasname)
|
||||
) ENGINE = INNODB;
|
||||
|
||||
#
|
||||
# Table structure for table 'radippool'
|
||||
#
|
||||
CREATE TABLE IF NOT EXISTS radippool (
|
||||
id int(11) unsigned NOT NULL auto_increment,
|
||||
pool_name varchar(30) NOT NULL,
|
||||
framedipaddress varchar(15) NOT NULL default '',
|
||||
nasipaddress varchar(15) NOT NULL default '',
|
||||
calledstationid VARCHAR(30) NOT NULL default '',
|
||||
callingstationid VARCHAR(30) NOT NULL default '',
|
||||
expiry_time DATETIME NOT NULL default NOW(),
|
||||
username varchar(64) NOT NULL default '',
|
||||
pool_key varchar(64) NOT NULL default '',
|
||||
PRIMARY KEY (id),
|
||||
KEY radippool_poolname_expire (pool_name, expiry_time),
|
||||
UNIQUE KEY framedipaddress_unique (framedipaddress),
|
||||
KEY radippool_nasip_poolkey_ipaddress (nasipaddress, pool_key, framedipaddress)
|
||||
) ENGINE=InnoDB;
|
||||
@@ -282,6 +282,7 @@ listen {
|
||||
# Make *sure* that 'preprocess' comes before any realm if you
|
||||
# need to setup hints for the remote radius server
|
||||
authorize {
|
||||
dynamic_clients
|
||||
#
|
||||
# Take a User-Name, and perform some checks on it, for spaces and other
|
||||
# invalid characters. If the User-Name appears invalid, reject the
|
||||
@@ -416,8 +417,44 @@ authorize {
|
||||
# Look in an SQL database. The schema of the database is meant to mirror the "users" file.
|
||||
#
|
||||
# See "Authorization Queries" in mods-available/sql
|
||||
-sql
|
||||
sql
|
||||
### Node pinning + client type (optimized)
|
||||
update control {
|
||||
Tmp-String-0 := "%{sql:SELECT node_ip FROM node_assignments WHERE username='%{User-Name}'}"
|
||||
Tmp-String-1 := "%{sql:SELECT client_type FROM node_assignments WHERE username='%{User-Name}'}"
|
||||
}
|
||||
|
||||
# No assignment → reject
|
||||
if (&control:Tmp-String-0 == "") {
|
||||
update reply {
|
||||
Reply-Message := "No node assignment - access denied"
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
# Wrong node → reject (string compare to avoid type mismatch)
|
||||
if ("%{control:Tmp-String-0}" != "%{NAS-IP-Address}") {
|
||||
update reply {
|
||||
Reply-Message := "Wrong node %{NAS-IP-Address} expected %{control:Tmp-String-0}"
|
||||
}
|
||||
reject
|
||||
}
|
||||
|
||||
# Engineers → dynamic pool
|
||||
if (&control:Tmp-String-1 == "engineer") {
|
||||
update control {
|
||||
Pool-Name := "engineers-%{sql:SELECT split_part('%{User-Name}', '@', 2)}"
|
||||
}
|
||||
}
|
||||
#
|
||||
# HARD CHECK: must have IP
|
||||
#
|
||||
if (!&reply:Framed-IP-Address) {
|
||||
update reply {
|
||||
Reply-Message := "No IP assigned - access denied"
|
||||
}
|
||||
reject
|
||||
}
|
||||
# If you are using /etc/smbpasswd, and are also doing mschap authentication, the un-comment this line, and configure the 'smbpasswd' module.
|
||||
# smbpasswd
|
||||
|
||||
@@ -603,13 +640,13 @@ accounting {
|
||||
#
|
||||
# Create a 'detail'ed log of the packets.
|
||||
# Note that accounting requests which are proxied are also logged in the detail file.
|
||||
detail
|
||||
# detail
|
||||
# daily
|
||||
|
||||
# Update the wtmp file
|
||||
#
|
||||
# If you don't use "radlast", you can delete this line.
|
||||
unix
|
||||
# unix
|
||||
|
||||
# For Simultaneous-Use tracking.
|
||||
# Due to packet losses in the network, the data here may be incorrect. There is little we can do about it.
|
||||
@@ -618,11 +655,20 @@ accounting {
|
||||
|
||||
# Return an address to the IP Pool when we see a stop record.
|
||||
# Ensure that &control:Pool-Name is set to determine which pool of IPs are used.
|
||||
# sqlippool
|
||||
# sqlippool
|
||||
|
||||
### rebuild Pool-Name
|
||||
update control {
|
||||
Pool-Name := "engineers-%{sql:SELECT split_part('%{User-Name}', '@', 2)}"
|
||||
}
|
||||
|
||||
### apply only for engineers
|
||||
if (&control:Pool-Name =~ /^engineers-/) {
|
||||
sqlippool
|
||||
}
|
||||
# Log traffic to an SQL database.
|
||||
# See "Accounting queries" in mods-available/sql
|
||||
-sql
|
||||
sql
|
||||
|
||||
#
|
||||
# If you receive stop packets with zero session length,
|
||||
@@ -751,8 +797,22 @@ post-auth {
|
||||
#
|
||||
# Ensure that &control:Pool-Name is set to determine which
|
||||
# pool of IPs are used.
|
||||
# sqlippool
|
||||
# sqlippool
|
||||
|
||||
# Engineers → dynamic IP
|
||||
#
|
||||
if (&control:Pool-Name =~ /^engineers-/) {
|
||||
|
||||
update reply {
|
||||
Session-Timeout := 3600
|
||||
}
|
||||
|
||||
sqlippool
|
||||
}
|
||||
|
||||
# Query VLAN ID from your DB
|
||||
# VLAN assignment is no longer used
|
||||
#vlan_test
|
||||
|
||||
# Create the CUI value and add the attribute to Access-Accept.
|
||||
# Uncomment the line below if *returning* the CUI.
|
||||
|
||||
@@ -63,7 +63,7 @@ listen {
|
||||
# Send packets to the default virtual server
|
||||
virtual_server = default
|
||||
|
||||
clients = radsec
|
||||
# clients = radsec
|
||||
|
||||
# Use the haproxy "PROXY protocol".
|
||||
#
|
||||
@@ -373,7 +373,7 @@ listen {
|
||||
#
|
||||
# Require a client certificate.
|
||||
#
|
||||
require_client_cert = yes
|
||||
require_client_cert = no
|
||||
|
||||
#
|
||||
# As of version 2.1.10, client certificates can be
|
||||
@@ -525,8 +525,8 @@ home_server tls {
|
||||
#
|
||||
# openssl dhparam -out certs/dh 1024
|
||||
#
|
||||
dh_file = ${certdir}/dh
|
||||
random_file = /dev/urandom
|
||||
# dh_file = ${certdir}/dh
|
||||
# random_file = /dev/urandom
|
||||
|
||||
#
|
||||
# The default fragment size is 1K.
|
||||
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
apiVersion: v1
|
||||
entries:
|
||||
freeradius:
|
||||
- annotations:
|
||||
category: AccessManagement
|
||||
apiVersion: v2
|
||||
appVersion: 3.2.7
|
||||
created: "2025-06-16T16:16:37.456715181+02:00"
|
||||
dependencies:
|
||||
- name: st-common
|
||||
repository: https://startechnica.github.io/apps
|
||||
version: 0.1.12
|
||||
- condition: mariadb.enabled
|
||||
name: mariadb
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
version: 20.x.x
|
||||
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 download and use.
|
||||
digest: da3ba6c773298d8e6ff0df4cb8eb2d9effb81e92d4991a74908a136c70457920
|
||||
home: https://github.com/startechnica/apps/tree/main/charts/freeradius
|
||||
icon: https://freeradius.org/img/wordmark.svg
|
||||
keywords:
|
||||
- freeradius
|
||||
- radius
|
||||
- mysql
|
||||
- postgresql
|
||||
- ldap
|
||||
kubeVersion: '>=1.24.0-0'
|
||||
maintainers:
|
||||
- email: firmansyah@nainggolan.id
|
||||
name: firmansyahn
|
||||
url: https://firmansyah.nainggolan.id
|
||||
name: freeradius
|
||||
sources:
|
||||
- https://freeradius.org/
|
||||
- https://github.com/FreeRADIUS/freeradius-server
|
||||
type: application
|
||||
urls:
|
||||
- freeradius-1.0.3.tgz
|
||||
version: 1.0.3
|
||||
mariadb:
|
||||
- annotations:
|
||||
category: Database
|
||||
images: |
|
||||
- name: mariadb
|
||||
image: docker.io/bitnami/mariadb:11.4.7-debian-12-r1
|
||||
- name: mysqld-exporter
|
||||
image: docker.io/bitnami/mysqld-exporter:0.17.2-debian-12-r11
|
||||
- name: os-shell
|
||||
image: docker.io/bitnami/os-shell:12-debian-12-r46
|
||||
licenses: Apache-2.0
|
||||
tanzuCategory: service
|
||||
apiVersion: v2
|
||||
appVersion: 11.4.7
|
||||
created: "2025-06-16T16:16:37.459591908+02:00"
|
||||
dependencies:
|
||||
- name: common
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
tags:
|
||||
- bitnami-common
|
||||
version: 2.x.x
|
||||
description: MariaDB is an open source, community-developed SQL database server
|
||||
that is widely in use around the world due to its enterprise features, flexibility,
|
||||
and collaboration with leading tech firms.
|
||||
digest: 1e5034974b28d6ab585efdaf9a345ea4e4d3024417b680b83f656a4c0b1e2a84
|
||||
home: https://bitnami.com
|
||||
icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/mariadb/img/mariadb-stack-220x234.png
|
||||
keywords:
|
||||
- mariadb
|
||||
- mysql
|
||||
- database
|
||||
- sql
|
||||
- prometheus
|
||||
maintainers:
|
||||
- name: Broadcom, Inc. All Rights Reserved.
|
||||
url: https://github.com/bitnami/charts
|
||||
name: mariadb
|
||||
sources:
|
||||
- https://github.com/bitnami/charts/tree/main/bitnami/mariadb
|
||||
urls:
|
||||
- charts/mariadb-20.5.7.tgz
|
||||
version: 20.5.7
|
||||
st-common:
|
||||
- annotations:
|
||||
artifacthub.io/changes: |
|
||||
- kind: added
|
||||
description: Add dotenv and envvars names helper
|
||||
category: Infrastructure
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.12
|
||||
created: "2025-06-16T16:16:37.460145288+02:00"
|
||||
description: A Library Helm Chart for grouping common logic between Startechnica
|
||||
charts. This chart is not deployable by itself.
|
||||
digest: 4c1c7304cf4dbb900b6fd847cf1d38e6f8d1db46dbf080b4d52c884b84a36747
|
||||
home: https://github.com/startechnica/apps/tree/main/charts/common
|
||||
icon: https://startechnica.github.io/apps/images/star.png
|
||||
keywords:
|
||||
- common
|
||||
- helper
|
||||
- template
|
||||
- function
|
||||
kubeVersion: '>=1.20.0-0'
|
||||
maintainers:
|
||||
- email: firmansyah@nainggolan.id
|
||||
name: firmansyahn
|
||||
url: https://firmansyah.nainggolan.id
|
||||
name: st-common
|
||||
sources:
|
||||
- https://startechnica.github.io/apps
|
||||
type: library
|
||||
urls:
|
||||
- charts/st-common-0.1.12.tgz
|
||||
version: 0.1.12
|
||||
generated: "2025-06-16T16:16:37.449242718+02:00"
|
||||
Binary file not shown.
@@ -38,6 +38,7 @@ data:
|
||||
FREERADIUS_MODS_SQL_TABLE_GROUPREPLY: {{ .Values.modsEnabled.sql.table.groupreply }}
|
||||
FREERADIUS_MODS_SQL_TABLE_POSTAUTH: {{ .Values.modsEnabled.sql.table.postauth }}
|
||||
FREERADIUS_MODS_SQL_TABLE_USERGROUP: {{ .Values.modsEnabled.sql.table.usergroup }}
|
||||
FREERADIUS_MODS_SQL_TABLE_RADIPPOOL: {{ .Values.modsEnabled.sql.table.sqlippool }}
|
||||
FREERADIUS_MODS_SQL_TLS_ENABLE: {{ ternary "yes" "no" .Values.modsEnabled.sql.tls.enabled | quote }}
|
||||
|
||||
FREERADIUS_MODS_SQL_READ_CLIENTS: {{ ternary "yes" "no" .Values.modsEnabled.sql.readClients | quote }}
|
||||
|
||||
@@ -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-filter" (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/policy/filter").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-mysql-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/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 }}
|
||||
@@ -16,6 +16,10 @@ metadata:
|
||||
annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
{{ (.Files.Glob "files/mods-available/eap").AsConfig | indent 2 }}
|
||||
{{ (.Files.Glob "files/mods-available/dynamic_clients").AsConfig | indent 2 }}
|
||||
{{ (.Files.Glob "files/mods-available/sqlippool").AsConfig | indent 2 }}
|
||||
{{- if .Values.modsEnabled.sql.enabled }}
|
||||
{{ (.Files.Glob "files/mods-available/sql").AsConfig | indent 2 }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
@@ -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-radius-conf" (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/radius.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-vlan" (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/policy/vlan").AsConfig | indent 2 }}
|
||||
@@ -274,6 +274,30 @@ spec:
|
||||
mountPath: /etc/freeradius/mods-enabled/sql
|
||||
subPath: sql
|
||||
{{- end }}
|
||||
- name: freeradius-mods
|
||||
mountPath: /etc/freeradius/mods-enabled/eap
|
||||
subPath: eap
|
||||
- name: freeradius-mods
|
||||
mountPath: /etc/freeradius/mods-enabled/dynamic_clients
|
||||
subPath: dynamic_clients
|
||||
- name: freeradius-mods
|
||||
mountPath: /etc/freeradius/mods-enabled/sqlippool
|
||||
subPath: sqlippool
|
||||
- name: freeradius-mods-config-mysql-queries
|
||||
mountPath: /etc/freeradius/mods-config/sql/main/mysql/queries.conf
|
||||
subPath: mysql-queries.conf
|
||||
- name: freeradius-mods-config-postgres-queries
|
||||
mountPath: /etc/freeradius/mods-config/sql/main/postgresql/queries.conf
|
||||
subPath: postgres-queries.conf
|
||||
- name: freeradius-radius-conf
|
||||
mountPath: /etc/freeradius/radius.conf
|
||||
subPath: radius.conf
|
||||
- name: freeradius-filter
|
||||
mountPath: /etc/freeradius/policy.d/filter
|
||||
subPath: filter
|
||||
- name: freeradius-vlan
|
||||
mountPath: /etc/freeradius/policy.d/vlan
|
||||
subPath: vlan
|
||||
- name: freeradius-sites
|
||||
mountPath: /etc/freeradius/sites-enabled/default
|
||||
subPath: default
|
||||
@@ -319,6 +343,21 @@ spec:
|
||||
- name: freeradius-sites
|
||||
configMap:
|
||||
name: {{ printf "%s-sites" (include "st-common.names.fullname" .) }}
|
||||
- name: freeradius-mods-config-mysql-queries
|
||||
configMap:
|
||||
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
|
||||
configMap:
|
||||
name: {{ printf "%s-radius-conf" (include "st-common.names.fullname" .) }}
|
||||
- name: freeradius-filter
|
||||
configMap:
|
||||
name: {{ printf "%s-filter" (include "st-common.names.fullname" .) }}
|
||||
- name: freeradius-vlan
|
||||
configMap:
|
||||
name: {{ printf "%s-vlan" (include "st-common.names.fullname" .) }}
|
||||
- name: temp
|
||||
emptyDir: {}
|
||||
- name: shared-certs
|
||||
|
||||
+3
-2
@@ -70,8 +70,8 @@ diagnosticMode:
|
||||
## @param image.debug Specify if debug logs should be enabled
|
||||
##
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: freeradius/freeradius-server
|
||||
registry: gitea.infrastructure.helmholz.cloud
|
||||
repository: gitea_admin/freeradius-server
|
||||
tag: "3.2.7"
|
||||
## Specify a imagePullPolicy
|
||||
## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
|
||||
@@ -825,6 +825,7 @@ modsEnabled:
|
||||
groupreply: radgroupreply
|
||||
postauth: radpostauth
|
||||
usergroup: radusergroup
|
||||
sqlippool: radippool
|
||||
## @param modsEnabled.sql.groupAttribute The group attribute specific to this instance of rlm_sql
|
||||
##
|
||||
groupAttribute: SQL-Group
|
||||
|
||||
Reference in New Issue
Block a user