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.
-
Analyze 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.