Documentation

scripts

The scripts clause registers named Lua scripts that can be invoked from AAA pipelines (authentication / authorization / accounting hooks, maps, or other extensible points). Scripts enable custom logic, enrichment, transformation, and external integration without recompiling the server.

Each lua block defines exactly one script by name. Source can be loaded from a file (filename) or embedded inline using content. A script is compiled the first time it is executed (or explicitly requested), then cached until its version changes (e.g. configuration reload with modified content).

Structure

scripts {
    lua "auth_enrichment" {
        filename "./lua/auth_enrichment.lua";
    }

    lua "inline_example" {
        content "
            function main(context, previous)
                -- context is an AAA context object
                -- previous is the Option<bool> result from prior action (may be nil)
                -- Return:
                --   true  -> accept (if used in a decision point)
                --   false -> reject
                --   nil   -> no explicit decision
                return nil
            end
        ";
    }
}

Blocks and Statements

ElementContextRequiredDescription
scripts { ... }top-levelNo (only needed if you use scripts)Container for script definitions
lua "NAME" { ... }inside scriptsYes (≥1)Declares a script with the given name
filename "path";inside luaOne of filename or contentLoads Lua source from file
content "…";inside luaOne of filename or contentInline Lua source (quoted multi-line string)

Exactly one of filename or content must be present in a lua block. If both are provided the configuration is invalid.

Naming

Script names are case sensitive. Reusing a name overwrites the earlier definition in the same configuration pass (last one wins), but you should treat duplicates as a configuration smell and avoid them.

Runtime Model (Summary)

  1. Configuration parser registers all script definitions (name + source origin).
  2. When a script is executed the runtime:
    • Compiles it (if not yet compiled).
    • Caches the compiled function keyed by script name and a version token.
  3. Subsequent invocations reuse the compiled function unless the script changed.
  4. Script runs inside a sandboxed Lua VM with restricted environment (no direct uncontrolled filesystem or OS access unless exposed explicitly).
  5. Script receives:
    • An AAA context userdata exposing sub-contexts (protocol, acct, user data, etc.).
    • The previous optional boolean result (if part of a sequential pipeline).

Return semantics:

  • true → Treated as an explicit accept (where meaningful).
  • false → Treated as an explicit reject.
  • nil → Neutral; processing continues.

(Exact decision integration depends on where you inject the script; a neutral return simply delegates to subsequent pipeline steps.)

Common Use Cases

Use CaseApproach
Attribute enrichmentFetch external values (HTTP backend + mapping) then augment response via script
Conditional policy tuningInspect combined attributes and set control variables
Audit taggingLog structured events (using provided logging or by setting response fields)
Dynamic authorizationCompute accept/reject based on composite or temporal logic

Example Script (File-Based)

./lua/auth_enrichment.lua:

function main(context, previous)
    -- Example: add a tag if realm matches
    local realm = context:aaa().realm
    if realm == "example.com" then
        -- Set response attribute via helper (pseudo accessor)
        -- context:set("response.reply-message", "Welcome example.com user")
    end
    return nil
end

Configuration:

scripts {
    lua "auth_enrichment" {
        filename "./lua/auth_enrichment.lua";
    }
}

Then used inside an authorization block (pseudo):

authorization {
    # call script "auth_enrichment"
    script "auth_enrichment";
    accept;
}