@pipeline
Reusable named pipelines
The @pipeline block allows defining reusable named pipelines that can be
invoked from multiple places in the configuration. This is useful for defining
common processing logic that can be shared across different policies or
handlers.
Note: The
@pipelineprefix is the recommended syntax. The barepipelineandtemplatekeywords are deprecated and emit warnings. Use@pipelinefor new configurations.
Pipelines are defined inside an aaa block but can be placed in a different
configuration file from the handlers that invoke them. Radiator loads all
.radconf files from the configuration directory in alphabetical order and
merges their aaa blocks, so a pipeline defined in one file is available to
any handler in another file. A common pattern is to keep pipeline definitions
in an early-loading file (for example 15_logging-pipelines.radconf) and
invoke them from policy files that load later (for example
50_policies.radconf).
Examples
Logging
A common use case is to define a reusable logging pipeline:
aaa {
@pipeline "LOG_AUTHENTICATION" {
log "AUTHENTICATION" {
json {
"Timestamp" datetime.timestamp;
"AAA-Identity" aaa.identity;
"AAA-Method" aaa.method;
"Reason" aaa.reason;
"Result" "%{aaa.result}";
"Errors" "%{aaa.errors}";
}
}
}
}
The pipeline is invoked using the invoke action:
@final-execute {
invoke "LOG_AUTHENTICATION";
}
LDAP bind authentication
Pipelines can contain any actions, including backend calls. For example, define a reusable LDAP bind authentication pipeline that first searches for the user's DN and then binds with the user's password:
aaa {
@pipeline "LDAP_BIND_AUTH" {
backend { name "LDAP"; query "FIND_USER"; }
backend { name "LDAP"; query "BIND_USER"; }
}
}
@execute {
invoke "LDAP_BIND_AUTH";
}
Shared configuration variables
Pipelines can also be used to set shared configuration variables that multiple handlers need. For example, define a pipeline that sets common credential variables:
aaa {
@pipeline "SET_CREDENTIALS" {
modify {
vars.aaa.oauth2.token-url = "https://example.com/oauth2/v2.0/token";
vars.aaa.oauth2.client = "APPLICATION_ID";
vars.aaa.oauth2.secret = "APPLICATION_SECRET";
}
}
}
Then invoke it at the beginning of a handler's execute block:
@execute {
invoke "SET_CREDENTIALS";
backend {
name "MY_OAUTH2_BACKEND";
query "AUTH_USERS";
}
}
Passing variables to pipelines
Named pipelines do not support arguments, but you can simulate them by
setting vars.* values before invoking the pipeline. The pipeline then
reads those variables to customize its behavior.
For example, define a reusable VLAN assignment pipeline that reads the VLAN ID from a variable:
aaa {
@pipeline "ASSIGN_VLAN" {
modify {
radius.reply.attr.Tunnel-Type:1 = "VLAN";
radius.reply.attr.Tunnel-Medium-Type:1 = "Ether_802";
radius.reply.attr.Tunnel-Private-Group-Id:1 = vars.vlan_id;
}
}
}
Each handler sets the desired VLAN ID before invoking the pipeline:
@execute {
modify vars.vlan_id = "100";
invoke "ASSIGN_VLAN";
}
@execute {
modify vars.vlan_id = "200";
invoke "ASSIGN_VLAN";
}