A Python REST API on top of the FreeRADIUS database for automation purposes.
- It provides an object-oriented view of the database schema.
- It implements logic to ensure data consistency.
- It works with MySQL, MariaDB, PostgreSQL and SQLite using DB-API 2.0 compliant drivers.
Number of results is limited to 100 by default.
curl -X 'GET' http://localhost:8000/api/v1/nas
#> 200 OK
[
{"nasname": "3.3.3.3", "shortname": "my-super-nas", "secret": "my-super-secret"},
{"nasname": "4.4.4.4", "shortname": "my-other-nas", "secret": "my-other-secret"}
]curl -X 'GET' http://localhost:8000/api/v1/users
#> 200 OK
[
{
"username": "alice@adsl",
"checks": [{"attribute": "Cleartext-Password", "op": ":=", "value": "alice-pass"}],
"replies": [
{"attribute": "Framed-IP-Address", "op": ":=", "value": "10.0.0.2"},
{"attribute": "Framed-Route", "op": "+=", "value": "192.168.1.0/24"}
],
"groups": [{"groupname": "100m", "priority": 1}]
},
{
"username": "bob",
"checks": [{"attribute": "Cleartext-Password", "op": ":=", "value": "bob-pass"}],
"replies": [
{"attribute": "Framed-IP-Address", "op": ":=", "value": "10.0.0.1"}
],
"groups": [{"groupname": "100m", "priority": 1}]
}
]curl -X 'GET' http://localhost:8000/api/v1/groups
#> 200 OK
[
{
"groupname": "100m",
"checks": [],
"replies": [{"attribute": "Filter-Id", "op": ":=", "value": "100m"}],
"users": [
{"username": "bob", "priority": 1},
{"username": "alice@adsl", "priority": 1}
]
}
]curl -X 'GET' http://localhost:8000/api/v1/huntgroups
#> 200 OK
[
{
"groupname": "ap-group",
"nas_ip_address": "192.168.1.10",
"nas_port_id": "ap-01"
}
]curl -X 'GET' http://localhost:8000/api/v1/nas/3.3.3.3curl -X 'GET' http://localhost:8000/api/v1/users/evecurl -X 'GET' http://localhost:8000/api/v1/groups/100mcurl -X 'POST' \
'http://localhost:8000/api/v1/nas' \
-H 'Content-Type: application/json' \
-d '{
"nasname": "5.5.5.5",
"shortname": "my-nas",
"secret": "my-secret"
}'The update strategy follows RFC 7396 (JSON Merge Patch) guidelines:
- Omitted fields are not modified.
Nonevalue means removal.- A list field can only be overwritten (replaced).
curl -X 'PATCH' \
'http://localhost:8000/api/v1/nas/5.5.5.5' \
-H 'Content-Type: application/json' \
-d '{
"secret": "new-secret"
}'curl -X 'DELETE' http://localhost:8000/api/v1/nas/5.5.5.5An instance of the FreeRADIUS server is NOT needed for testing. The focus is on the FreeRADIUS database. As long as you have one (or a Docker container for it), the API can run.
The project includes a Docker setup for easy testing.
git clone https://github.com/angely-dev/freeradius-api.git
cd freeradius-api/docker
docker compose up -d --buildThen go to: http://localhost:8000/docs
- Get the project:
git clone https://github.com/angely-dev/freeradius-api.git
cd freeradius-api- Create and activate a virtual environment:
python3 -m venv venv
source venv/bin/activate- Install dependencies:
pip install -r requirements.txt- Configure environment variables:
Copy the example environment file and edit it to match your database settings.
cd src
cp .env.example .env
nano .envSet DB_DRIVER, DB_HOST, DB_USER, DB_PASS, etc.
- Run the API:
uvicorn api:app --reloadThen go to: http://localhost:8000/docs
Configuration is managed via environment variables (or a .env file in the src directory).
| Variable | Description | Default |
|---|---|---|
DB_DRIVER |
Database driver (mysql.connector, psycopg, sqlite3, etc.) |
mysql.connector |
DB_HOST |
Database host | mydb |
DB_PORT |
Database port | 3306 |
DB_NAME |
Database name | raddb |
DB_USER |
Database user | raduser |
DB_PASS |
Database password | radpass |
ITEMS_PER_PAGE |
Pagination limit | 100 |
API_URL |
Base URL for Link headers | http://0.0.0.0:8000 |
X_API_KEY |
API Key(s) for authentication | None |
Results are paginated using Keyset pagination (aka WHERE + LIMIT).
Pagination is done through HTTP response headers (as per RFC 8288). The Link header contains the URL for the next page.
$ curl -X 'GET' -i http://localhost:8000/api/v1/users
HTTP/1.1 200 OK
link: <http://localhost:8000/api/v1/users?from_username=acb>; rel="next"
...Authentication can be enabled by setting the X_API_KEY environment variable.
-
Set the key in
.env:X_API_KEY=my-secret-key
Or for multiple keys:
X_API_KEY=key1,key2,key3
-
Make authenticated requests:
curl -X 'GET' -H 'X-API-Key: my-secret-key' http://localhost:8000/api/v1/users
The header name can be customized via X_API_KEY_HEADER.