Raduat
The raduat tool is for automated testing of RADIUS server configurations and functionality. Raduat is a shell script used for writing test suites as required by your organization’s eco-system. This tool reads test files and uses radclient to send the test requests. Server responses are compared against a response filter file that contains the expected output.
Raduat helps identify configuration and functionality issues ensuring that the FreeRADIUS server is operating correctly.
Getting Started
To use raduat successfully, follow these steps:
-
Create the test files.
-
Create the response filter files.
-
Run the tests.
-
Analyse the results.
-
Fix any issues and update the relevant files.
-
Re-run the tests.
Download the latest version of raduat from github.
The raduat tool supports PAP and CHAP authentications only (no EAP support). Raduat is often used by ISPs and carriers that require end to end testing involving complex business logic using basic authentication methods.
Create a test request
A test request consists of <attribute><op><value> pairs, separated
by newlines.
Attribute
Every request must contain a
Packet-Type=[Access-Request|Accounting-Request] pair, to set the
type of test request.
In addition to Packet-Type it may contain any attribute (including
VSAs) found in the FreeRADIUS dictionaries.
Commonly used attributes are:
-
User-Name -
User-Password -
NAS-IP-Address -
Acct-Session-Id -
NAS-Port-ID -
Acct-Session-Time
Operators (op)
The operator (op) must be one of the assignment operators below.
| Parameter | Description |
|---|---|
|
Sets the value of the attribute |
|
Replaces the value of the attribute |
|
Append the value of the attribute to the list |
Value
Only static values are supported. In a future release, backtick (exec) expansion may be added.
Strings must be wrapped in single quotes, any other values remain unquoted.
Binary attributes values may be specified as an unquoted string with a
0x prefix e.g. 0xffffff
Create a response filter file
A response filter consists of <attribute><op><value> pairs,
separated by newlines.
Response filters are used to verify that the response received from the server matches what’s expected.
The pairs in the response filter do not need to be in the same order as the server response. However, every attribute in the server response must be matched by a line in the response filter.
Attributes
Every response filter must contain a
Response-Packet-Type=[Access-Accept|Access-Reject|Accounting-Response]
pair to set the type of response expected.
In addition to Response-Packet-Type it may contain any attribute
(including VSAs) found in the FreeRADIUS dictionaries.
Commonly used attributes are:
* Reply-Message
* User-Name
* Class
* Framed-IP-Address
* Framed-Route
* Session-Timeout
Operators (op)
The operator (op) must be one of the comparison operators below.
| Parameter | Description | Parameter | Description |
|---|---|---|---|
|
Less than |
|
Greater than |
|
Less than or equal to |
|
Greater than or equal to |
|
Equal to |
|
Not equal to |
|
Matches |
|
Does not match |
|
Present |
|
Not present |
Value
Value format is the same as the request.
Create a test suite
By default raduat looks for a folder relative to itself called
tests.
If it finds one, raduat tries executing each of the test requests in
lexicographical order. The raduat tool also works with with a
directory hierarchy. In this case the tests are executed depth first
then in lexicographical order. This is to allow easy organization of
tests.
Only files with names that match the pattern test[0-9]{3}.* are
processed. Each request file must also be paired with a response
filter file. A response filter file uses the same name as the request
file appended with an _expected suffix.
For example, the response filter file for test000_check_static_ip
is test000_check_static_ip_expected.
Example
mkdir -p ./tests/static_ip echo "Packet-Type=Access-Request User-Name=test_user001@test.realm User-Password=testing123" >> ./tests/static_ip/test000_check_static_ip echo "Response-Packet-Type==Access-Accept Framed-IP-address==192.168.0.1" >> ./tests/static_ip/test000_check_static_ip_expected echo "Packet-Type=Access-Request User-Name=test_user002@test.realm User-Password=testing123" >> ./tests/static_ip/test001_check_static_ip echo "Response-Packet-Type==Access-Accept Framed-IP-address==192.168.0.2" >> ./tests/static_ip/test001_check_static_ip_expected
Run the tests
By default radaut will execute tests in parallel batches of 20. If you
want to execute tests one at a time, either add # serial to the
top of the file, or pass -p 1.
Arguments
Command line arguments can be found with raduat -h. They can be
used to specify the server/port/secret to run the tests against. By
default the server is 127.0.0.1 the port is automatically
determined by Packet-Type and the secret is testing123.
-h |
Display this help message |
-H <host>[:port] |
Send test packets to specified host and port. Defaults = 127.0.0.1 |
-v |
Verbose mode |
-p <number> |
Run tests in parallel. Defaults = 20 |
-s <secret> |
Shared secret |
-c <cluster> |
Specify cluster type one of ($cluster_types) |
-r <type> |
Specify server role one of ($role_types) |
Environmental variables
-
TESTDIR- The directory containing the tests. -
RADCLIENT- Path to the radclient binary. -
FILTER_SUFFIX- The suffix added to the request file name to find response filters. Defaults to_expected. -
DICTPATH- Path to alternative RADIUS dictionaries.
Example test execution
Running the above test requests/response filters against a dummy configuration:
authorize {
switch User-Name {
case 'test_user001@test.realm' {
update reply {
Framed-IP-Address := 192.168.0.1
}
}
case 'test_user002@test.realm' {
update reply {
Framed-IP-Address := 192.168.0.3
}
}
}
update control {
Auth-Type := Accept
}
}
Produces the following output:
$ ./raduat Executing 2 test(s) from ./tests Executing specified tests Use -v to see full list Sent Access-Request Id 197 from 0.0.0.0:55331 to 127.0.0.1:1812 length 63 Sent Access-Request Id 149 from 0.0.0.0:55331 to 127.0.0.1:1812 length 63 Received Access-Accept Id 197 from 127.0.0.1:1812 to 0.0.0.0:0 length 26 Received Access-Accept Id 149 from 127.0.0.1:1812 to 0.0.0.0:0 length 26 (1) ./tests/static_ip/test001_check_static_ip: Response for failed filter: Attribute value "192.168.0.3" didn't match filter: Framed-IP-Address == 192.168.0.2 (Parallelized tests) One or more tests failed (radclient exited with 1) $ echo $? 1
Which is correct, as 192.168.0.3 != 192.168.0.2.
Adding -v gives us more verbose output, and also a summary of
packets sent/received:
./raduat -v
Executing 2 test(s) from ./tests
Executing specified tests:
./tests/static_ip/test000_check_static_ip
./tests/static_ip/test001_check_static_ip
Executing: radclient -f "/var/folders/5_/k_q1ccb94p3gcgk8r9yc8ssh0000gn/T/raduatXXX.f2cB3Kek:/var/folders/5_/k_q1ccb94p3gcgk8r9yc8ssh0000gn/T/raduatXXX.1RX7R8aL" -x -s -t "2" -r "3" -p "40" "127.0.0.1" auto "testing123"
Sent Access-Request Id 63 from 0.0.0.0:51512 to 127.0.0.1:1812 length 63
Packet-Type = Access-Request
User-Name = 'test_user001@test.realm'
User-Password = 'testing123'
Radclient-Test-Name := './tests/static_ip/test000_check_static_ip'
Sent Access-Request Id 147 from 0.0.0.0:51512 to 127.0.0.1:1812 length 63
Packet-Type = Access-Request
User-Name = 'test_user002@test.realm'
User-Password = 'testing123'
Radclient-Test-Name := './tests/static_ip/test001_check_static_ip'
Received Access-Accept Id 63 from 127.0.0.1:1812 to 0.0.0.0:0 length 26
Framed-IP-Address = 192.168.0.1
(0) ./tests/static_ip/test000_check_static_ip: Response passed filter
Received Access-Accept Id 147 from 127.0.0.1:1812 to 0.0.0.0:0 length 26
Framed-IP-Address = 192.168.0.3
(1) ./tests/static_ip/test001_check_static_ip: Response for failed filter: Attribute value "192.168.0.3" didn't match filter: Framed-IP-Address == 192.168.0.2
Packet summary:
Accepted : 2
Rejected : 0
Lost : 0
Passed filter : 1
Failed filter : 1
(Parallelised tests)
One or more tests failed (radclient exited with 1)
The tests to run can be filtered using glob patterns:
-
./raduat — 'static_ip/test000*'would execute only the first test in the static_ip suite. -
./raduat — 'static_ip/*'would execute all the static_ip tests.
This can be used to drill down, and only run the failing tests.