Endurance

RADIUS

Configuration

Get the RADIUS configuration. A stored shared secret is masked; with none stored it is empty.

GET /radius/config

curl
curl -X GET "https://appliance.example.com/api/v1/radius/config" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/config';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.get("https://appliance.example.com/api/v1/radius/config", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/config', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Get the RADIUS settings
  type: http
  seq: 1
}

get {
  url: https://{{node-0}}:{{port}}/api/v1/radius/config
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "RADIUS configuration",
  "data": [
    {
      "sharedSecret": "********",
      "port": 1812,
      "authProtocol": "PAP",
      "hosts": "<hosts>"
    }
  ]
}

Replace the RADIUS configuration and group mappings. The body is the whole section: a field it omits is stored at that field’s default rather than left as it was, so send the configuration back in full. A host and a shared secret are required whether or not enabled is set, which is why DELETE is the only way back to an empty section. Refused while a transaction is open. Commit or roll back the transaction first.

PUT /radius/config

This change is staged. Send PUT /services/apply to apply it.

Body parameters
enabled boolean

Whether RADIUS is offered as a login type.

hosts array of string Required

RADIUS servers, tried in order for failover.

port integer
sharedSecret string

Required until one is stored: read back masked, and the mask or an empty string keeps the stored secret, so only DELETE removes it. With none stored it reads back empty, and the mask or an empty string is refused. Never trimmed, so leading and trailing whitespace is part of the credential.

authProtocol PAP | CHAP | MS-CHAPv2
timeout string

How long to wait for a server to answer. A whole number of seconds, or a single time carrying a unit (s or m) such as 2m. At least 1 second. The value is echoed back exactly as it was sent.

retries integer

Resends per host when a server does not answer, so a host is tried retries + 1 times before the next one. 0 or greater.

nasIdentifier string

NAS-Identifier the appliance sends with each request.

groupAttribute string

Reply attribute the group membership is read from.

emailAttribute string
firstNameAttribute string
lastNameAttribute string
fallbackGroupId string

Appliance group id assigned when no mapping matches. Empty for none.

mappings array of object

Reply-attribute value to appliance group rules. Replaced wholesale.

Fields
attributeValue string

A value of groupAttribute to match on.

groupIds array of string

Appliance group ids granted to a user carrying that value.

curl
curl -X PUT "https://appliance.example.com/api/v1/radius/config" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true,
  "hosts": [
    "<hosts>"
  ],
  "port": 0,
  "sharedSecret": "<sharedSecret>",
  "authProtocol": "PAP",
  "timeout": "<timeout>",
  "retries": 0,
  "nasIdentifier": "<nasIdentifier>",
  "groupAttribute": "<groupAttribute>",
  "emailAttribute": "<emailAttribute>",
  "firstNameAttribute": "<firstNameAttribute>",
  "lastNameAttribute": "<lastNameAttribute>",
  "fallbackGroupId": "<fallbackGroupId>",
  "mappings": [
    {
      "attributeValue": "<attributeValue>",
      "groupIds": [
        "<groupIds>"
      ]
    }
  ]
}'
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/config';
$headers = [
    'Authorization: Bearer ' . $token,
    'Content-Type: application/json',
];

$payload = [
    'enabled' => true,
    'hosts' => [
        '<hosts>',
    ],
    'port' => 0,
    'sharedSecret' => '<sharedSecret>',
    'authProtocol' => 'PAP',
    'timeout' => '<timeout>',
    'retries' => 0,
    'nasIdentifier' => '<nasIdentifier>',
    'groupAttribute' => '<groupAttribute>',
    'emailAttribute' => '<emailAttribute>',
    'firstNameAttribute' => '<firstNameAttribute>',
    'lastNameAttribute' => '<lastNameAttribute>',
    'fallbackGroupId' => '<fallbackGroupId>',
    'mappings' => [
        [
            'attributeValue' => '<attributeValue>',
            'groupIds' => [
                '<groupIds>',
            ],
        ],
    ],
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}
payload = {
    "enabled": true,
    "hosts": [
        "<hosts>"
    ],
    "port": 0,
    "sharedSecret": "<sharedSecret>",
    "authProtocol": "PAP",
    "timeout": "<timeout>",
    "retries": 0,
    "nasIdentifier": "<nasIdentifier>",
    "groupAttribute": "<groupAttribute>",
    "emailAttribute": "<emailAttribute>",
    "firstNameAttribute": "<firstNameAttribute>",
    "lastNameAttribute": "<lastNameAttribute>",
    "fallbackGroupId": "<fallbackGroupId>",
    "mappings": [
        {
            "attributeValue": "<attributeValue>",
            "groupIds": [
                "<groupIds>"
            ]
        }
    ]
}

response = requests.put("https://appliance.example.com/api/v1/radius/config", headers=headers, json=payload)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/config', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "enabled": true,
  "hosts": [
    "<hosts>"
  ],
  "port": 0,
  "sharedSecret": "<sharedSecret>",
  "authProtocol": "PAP",
  "timeout": "<timeout>",
  "retries": 0,
  "nasIdentifier": "<nasIdentifier>",
  "groupAttribute": "<groupAttribute>",
  "emailAttribute": "<emailAttribute>",
  "firstNameAttribute": "<firstNameAttribute>",
  "lastNameAttribute": "<lastNameAttribute>",
  "fallbackGroupId": "<fallbackGroupId>",
  "mappings": [
    {
      "attributeValue": "<attributeValue>",
      "groupIds": [
        "<groupIds>"
      ]
    }
  ]
}),
});

const data = await response.json();
Bruno
meta {
  name: Update the RADIUS settings
  type: http
  seq: 1
}

put {
  url: https://{{node-0}}:{{port}}/api/v1/radius/config
  body: json
  auth: bearer
}

headers {
  Content-Type: application/json
}

auth:bearer {
  token: {{token}}
}

body:json {
  {
    "enabled": true,
    "hosts": [
      "<hosts>"
    ],
    "port": 0,
    "sharedSecret": "<sharedSecret>",
    "authProtocol": "PAP",
    "timeout": "<timeout>",
    "retries": 0,
    "nasIdentifier": "<nasIdentifier>",
    "groupAttribute": "<groupAttribute>",
    "emailAttribute": "<emailAttribute>",
    "firstNameAttribute": "<firstNameAttribute>",
    "lastNameAttribute": "<lastNameAttribute>",
    "fallbackGroupId": "<fallbackGroupId>",
    "mappings": [
      {
        "attributeValue": "<attributeValue>",
        "groupIds": [
          "<groupIds>"
        ]
      }
    ]
  }
}
Response
{
  "status": "success",
  "message": "RADIUS configuration updated",
  "data": []
}

Return the RADIUS configuration to its shipped state: disabled, with no host and no shared secret. The required fields are enforced on an update whether or not RADIUS is enabled, so this is the only way to empty the section. The JIT-provisioned RADIUS users are not affected. Refused while a transaction is open. Commit or roll back the transaction first.

DELETE /radius/config

This change is staged. Send PUT /services/apply to apply it.

curl
curl -X DELETE "https://appliance.example.com/api/v1/radius/config" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/config';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.delete("https://appliance.example.com/api/v1/radius/config", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/config', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Clear the RADIUS settings
  type: http
  seq: 1
}

delete {
  url: https://{{node-0}}:{{port}}/api/v1/radius/config
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "RADIUS configuration cleared",
  "data": []
}

Test the RADIUS connection

Test the RADIUS connection without saving. Every configured host is asked exactly once and reported on separately, so a host that does not answer is named rather than hidden behind one that does. Sending a username and password tests authentication and adds the reply attributes and the Groups they map to; omitting them tests only reachability and the shared secret. A masked or empty shared secret tests the stored one, and is refused when none is stored. Refused while a transaction is open. Commit or roll back the transaction first.

POST /radius/config/test

This change is staged. Send PUT /services/apply to apply it.

curl
curl -X POST "https://appliance.example.com/api/v1/radius/config/test" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/config/test';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.post("https://appliance.example.com/api/v1/radius/config/test", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/config/test', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Test the RADIUS connection
  type: http
  seq: 1
}

post {
  url: https://{{node-0}}:{{port}}/api/v1/radius/config/test
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "Connection test complete",
  "data": [
    {
      "stage": "authentication",
      "ok": true,
      "message": "radius1.example.com: accepted the credentials."
    },
    {
      "stage": "authentication",
      "ok": false,
      "message": "radius2.example.com: no response within the configured timeout"
    },
    {
      "stage": "attributes",
      "ok": true,
      "message": "Filter-Id = netadmins"
    },
    {
      "stage": "mapping",
      "ok": true,
      "message": "netadmins mapped to Groups: 5e1de37819dd5"
    }
  ]
}

List the RADIUS users

Get all JIT-provisioned RADIUS users

GET /radius/users

curl
curl -X GET "https://appliance.example.com/api/v1/radius/users" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/users';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.get("https://appliance.example.com/api/v1/radius/users", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/users', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: List the RADIUS users
  type: http
  seq: 1
}

get {
  url: https://{{node-0}}:{{port}}/api/v1/radius/users
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "All RADIUS users",
  "data": []
}

Users by ID

Get a RADIUS user by id

GET /radius/users/{id}

Path parameters
id string Required
curl
curl -X GET "https://appliance.example.com/api/v1/radius/users/{id}" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/users/{id}';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.get("https://appliance.example.com/api/v1/radius/users/{id}", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/users/{id}', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Get a RADIUS user
  type: http
  seq: 1
}

get {
  url: https://{{node-0}}:{{port}}/api/v1/radius/users/{id}
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "Get RADIUS user",
  "data": []
}

Enable or disable a RADIUS user Refused while a transaction is open. Commit or roll back the transaction first.

PUT /radius/users/{id}

This change is staged. Send PUT /services/apply to apply it.

Path parameters
id string Required

.Body parameters

disabled boolean Required
curl
curl -X PUT "https://appliance.example.com/api/v1/radius/users/{id}" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "disabled": true
}'
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/users/{id}';
$headers = [
    'Authorization: Bearer ' . $token,
    'Content-Type: application/json',
];

$payload = [
    'disabled' => true,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}
payload = {
    "disabled": true
}

response = requests.put("https://appliance.example.com/api/v1/radius/users/{id}", headers=headers, json=payload)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/users/{id}', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "disabled": true
}),
});

const data = await response.json();
Bruno
meta {
  name: Enable or disable a RADIUS user
  type: http
  seq: 1
}

put {
  url: https://{{node-0}}:{{port}}/api/v1/radius/users/{id}
  body: json
  auth: bearer
}

headers {
  Content-Type: application/json
}

auth:bearer {
  token: {{token}}
}

body:json {
  {
    "disabled": true
  }
}
Response
{
  "status": "success",
  "message": "RADIUS user updated",
  "data": []
}

Delete a RADIUS user record Refused while a transaction is open. Commit or roll back the transaction first.

DELETE /radius/users/{id}

This change is staged. Send PUT /services/apply to apply it.

Path parameters
id string Required
curl
curl -X DELETE "https://appliance.example.com/api/v1/radius/users/{id}" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/radius/users/{id}';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.delete("https://appliance.example.com/api/v1/radius/users/{id}", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/radius/users/{id}', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Delete a RADIUS user
  type: http
  seq: 1
}

delete {
  url: https://{{node-0}}:{{port}}/api/v1/radius/users/{id}
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "RADIUS user deleted",
  "data": []
}