2025-06-18

v10.28.0

Features

  • Add --check option to validate configuration files without starting the server
  • Add dictionary attributes and values to the radius.dict.* context
  • Read xml bindings as a multiline string
  • Remove need to escape single quotes inside double quotes
  • Enable tracing for all pipelines when RADIATOR_LOG_LEVEL=trace is set
  • Control AppLogger log level using RADIATOR_LOG_LEVEL environment variable
  • Support resource parameter in OAuth 2.0 client credentials form
  • Support inline certificates with multiline strings
  • Support regex modifiers like /something/i for case-insensitive matching
  • Support multivalues in map conditions
    • Check all multivalue values if they match map key

Bug Fixes

  • Prevent configuration from being saved when --force-configuration-file flag is used
  • Fix handling of spaces in expression brackets
  • Fix string matching in map conditions
  • Support OAuth2 responses where expires_in is provided as a string

Expressions

Double quotes now always mean a string string literal. Previously doubles quotes had no special meaning. It was context dependent whether a double quoted string was a string literal or a variable reference. Ex. "vars.foo" is now as string literal and vars.foo is a variable reference.

Migration

Policy

Double quoted string are now static strings. The quoted must be remove to get the variable value and not static string.

authorization {
    modify {
        radius.reply.attr.Alc-Subsc-ID-Str = "vars.sqlid";
    }
}

⬇️ ⬇️ ⬇️

authorization {
    modify {
        radius.reply.attr.Alc-Subsc-ID-Str = vars.sqlid;
    }
}

Same goes for conditionals etc.

Mappings

Mappings must be just non-quoted strings as they reference "variables"

mapping {
    "user.username" = "username";
    "user.password" = "password";
}

⬇️ ⬇️ ⬇️

mapping {
    user.username = username;
    user.password = password;
}

Bindings

Same goes for bindings

bindings {
    "http.body.username";
    "http.body.password";
}

⬇️ ⬇️ ⬇️

bindings {
    http.body.username;
    http.body.password;
}

JSON Path and XPath

JSON Path and XPath must be strings because they are complely different languages

mapping json {
    user.username = "$.user";
}
mapping xml {
    vars.challenge_received = "/BeginTwoWayAuthenticationResponse/AuthenticationResult";
    vars.challenge_result_value = "/BeginTwoWayAuthenticationResponse/Result/Value";
    vars.challenge_result_message = "/BeginTwoWayAuthenticationResponse/Result/Message";
}

Enum values

Enum values must be strings because they are not variables but rather fixed values. Even if encoded as a number on the wire.

radius.reply.attr.Tunnel-Type:2 = radius.Tunnel-Type.ATMP;

⬇️ ⬇️ ⬇️

radius.reply.attr.Tunnel-Type:2 = "radius.Tunnel-Type.ATMP";

Also a shortcut is now supported for enum values:

radius.reply.attr.Tunnel-Type:2 = "ATMP";

(the assigment already knowns the type)

JSON Logs

In JSON logs the keys must be strings but the values can be variable accessors or formatted strings.

json {
    "AAA-Identity" "aaa.identity";
    "Reason" "the reason %{aaa.reason}";
}

⬇️ ⬇️ ⬇️

json {
    "AAA-Identity" aaa.identity;
    "Reason" "the reason %{aaa.reason}";
}

🚨 Note that "AAA-Identity" "aaa.identity"; will work without an error but will log a static "aaa.identity" string and not the variable value!

Multiline strings

Python style multiline strings are supported in the configuration files. This allows you to write long strings without needing to concatenate them or use escape characters for newlines.

Example

sqlite "SQLITE" {
    query "FIND_USER" {
        query """
            SELECT
                id,
                name,
                email
            FROM
                users
            WHERE
                active = 1
        """;
    }
}