Skip to content

Commit

Permalink
Many fixes for rlm_cassandra
Browse files Browse the repository at this point in the history
Don't set timeouts or credentials unless they're actually specified

Use BATCH in accounting queries, to properly set acctstarttime where starts/interims have been missed.

Scrap all the ring buffer based logging code. During normal operation cassandra does write there anyway! The future handle usually provides the most relevant information about bad queries.
  • Loading branch information
arr2036 committed Jun 17, 2015
1 parent 0a29620 commit e12f016
Show file tree
Hide file tree
Showing 3 changed files with 603 additions and 165 deletions.
362 changes: 362 additions & 0 deletions raddb/mods-config/sql/main/cassandra/queries.conf
@@ -0,0 +1,362 @@
# -*- text -*-
#
# main/mysql/queries.conf-- MySQL configuration for default schema (schema.sql)
#
# $Id$

# Safe characters list for sql queries. Everything else is replaced
# with their mime-encoded equivalents.
# The default list should be ok
#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
# [client]
# 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}"

#######################################################################
# 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
#######################################################################

#
# 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}'"

authorize_reply_query = "\
SELECT id, username, attribute, value, op \
FROM ${authreply_table} \
WHERE username = '%{SQL-User-Name}'"

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 = '%{Sql-Group}'"

authorize_group_reply_query = "\
SELECT id, groupname, attribute, \
value, op \
FROM ${groupreply_table} \
WHERE groupname = '%{Sql-Group}'"

#######################################################################
# Simultaneous Use Checking Queries
#######################################################################
# simul_count_query - query for the number of current connections
# - If this is not defined, no simultaneouls 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.
#######################################################################

#
# Uncomment simul_count_query to enable simultaneous use checking
#
#simul_count_query = "\
# SELECT COUNT(*) \
# FROM ${acct_table1} \
# WHERE username = '%{SQL-User-Name}'"

simul_verify_query = "\
SELECT \
radacctid, acctsessionid, username, nasipaddress, nasportid, framedipaddress, \
callingstationid, framedprotocol \
FROM ${acct_table1} \
WHERE username = '%{SQL-User-Name}' \
AND acctstoptime = 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 exactly
# one query.
#
# Unlike other SQL drivers, the rlm_cassandra driver will always
# indicate a single row was updated. This is because the updates aren't
# applied synchronously, so there's really no clue as to what will be
# updated when the query is issued.
# This prevents the normal query failover from occurring, but that's ok
# as INSERTS are really UPSERTS so we can work around it.
#######################################################################
accounting {
reference = "%{tolower:type.%{Acct-Status-Type}.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

type {
#
# Because cassandra doesn't allow secondary indexes to be used in update statements
# applying acct on/off packets must be done outside of the server, by a script that
# first performs a SELECT to identify candidate rows, then closes out the sessions.
#
accounting-on {
query = "\
INSERT INTO radnasreboot (nasipaddress, timestamp) \
VALUES ('%{NAS-IP-Address}', %{%{integer:Event-Timestamp:-%l}});"
}

accounting-off {
query = "${..accounting-on.query}"
}

start {
#
# Insert a new record into the sessions table
#
query = "\
INSERT INTO ${....acct_table1} ( \
acctuniqueid, \
acctsessionid, \
username, \
realm, \
nasipaddress, \
nasportid, \
nasporttype, \
acctstarttime, \
acctupdatetime, \
acctstoptime, \
acctauthentic, \
connectinfo_start, \
acctinputoctets, \
acctoutputoctets, \
calledstationid, \
callingstationid, \
servicetype, \
framedprotocol, \
framedipaddress \
) VALUES ( \
'%{Acct-Unique-Session-Id}}', \
'%{Acct-Session-Id}', \
'%{SQL-User-Name}', \
'%{Realm}', \
'%{NAS-IP-Address}', \
'%{%{NAS-Port-Id}:-%{NAS-Port}}', \
'%{NAS-Port-Type}', \
%{%{integer:Event-Timestamp}:-%l}, \
%{%{integer:Event-Timestamp}:-%l}, \
null, \
'%{Acct-Authentic}', \
'%{Connect-Info}', \
0, \
0, \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
'%{Framed-IP-Address}' \
);"
}

interim-update {
query = "\
BEGIN BATCH \
INSERT INTO ${....acct_table1} ( \
acctuniqueid, \
acctsessionid, \
username, \
realm, \
nasipaddress, \
nasportid, \
nasporttype, \
acctupdatetime, \
acctstoptime, \
acctauthentic, \
connectinfo_start, \
acctinputoctets, \
acctoutputoctets, \
calledstationid, \
callingstationid, \
servicetype, \
framedprotocol, \
framedipaddress \
) VALUES ( \
'%{Acct-Unique-Session-Id}', \
'%{Acct-Session-Id}', \
'%{SQL-User-Name}', \
'%{Realm}', \
'%{NAS-IP-Address}', \
'%{%{NAS-Port-Id}:-%{NAS-Port}}', \
'%{NAS-Port-Type}', \
%{%{integer:Event-Timestamp}:-%l}, \
null, \
'%{Acct-Authentic}', \
'%{Connect-Info}', \
%{expr:(&Acct-Input-Gigawords << 32) | &Acct-Input-Octets}, \
%{expr:(&Acct-Output-Gigawords << 32) | &Acct-Output-Octets}, \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
'%{Framed-IP-Address}' \
); \
UPDATE ${....acct_table1} \
SET acctstarttime = %{expr:&Event-Timestamp - &Acct-Session-Time} \
WHERE acctuniqueid = '%{Acct-Unique-Session-Id}' \
IF acctstarttime = null; \
APPLY BATCH;"
}

stop {
query = "\
BEGIN BATCH \
INSERT INTO ${....acct_table1} ( \
acctuniqueid, \
acctsessionid, \
username, \
realm, \
nasipaddress, \
nasportid, \
nasporttype, \
acctupdatetime, \
acctstoptime, \
acctauthentic, \
connectinfo_start, \
acctinputoctets, \
acctoutputoctets, \
calledstationid, \
callingstationid, \
servicetype, \
framedprotocol, \
framedipaddress \
) VALUES ( \
'%{Acct-Unique-Session-Id}', \
'%{Acct-Session-Id}', \
'%{SQL-User-Name}', \
'%{Realm}', \
'%{NAS-IP-Address}', \
'%{%{NAS-Port-Id}:-%{NAS-Port}}', \
'%{NAS-Port-Type}', \
%{%{integer:Event-Timestamp}:-null}, \
null, \
'%{Acct-Authentic}', \
'%{Connect-Info}', \
%{expr:(&Acct-Input-Gigawords << 32) | &Acct-Input-Octets}, \
%{expr:(&Acct-Output-Gigawords << 32) | &Acct-Output-Octets}, \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
'%{Framed-IP-Address}' \
); \
UPDATE ${....acct_table1} \
SET acctstarttime = %{expr:&Event-Timestamp - &Acct-Session-Time} \
WHERE acctuniqueid = '%{Acct-Unique-Session-Id}' \
IF acctstarttime = null; \
APPLY BATCH;"
}
}
}


#######################################################################
# 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, pass, reply, authdate) \
VALUES ( \
'%{SQL-User-Name}', \
'%{%{User-Password}:-%{Chap-Password}}', \
'%{reply:Packet-Type}', \
'%S')"
}

0 comments on commit e12f016

Please sign in to comment.